【问题标题】:Is there a cleaner way to do this Group Query in MongoDB from Groovy?有没有更简洁的方法可以从 Groovy 在 MongoDB 中执行此组查询?
【发布时间】:2011-02-02 23:18:57
【问题描述】:

我正在学习 MongoDB。当前运行选择的语言是 Groovy。

通过尝试回答哪个宠物是最需要帮助的问题来处理组查询。

以下是我的第一次尝试,它糟糕。任何帮助清理此问题(或只是确认没有更清洁的方法)将不胜感激。

提前致谢!

package mongo.pets

import com.gmongo.GMongo
import com.mongodb.BasicDBObject
import com.mongodb.DBObject

class StatsController {

  def dbPets = new GMongo().getDB('needsHotel').getCollection('pets')

  //FIXME OMG THIS IS AWFUL!!!
  def index = {
    def petsNeed = 'a walk'

    def reduce = 'function(doc, aggregator) { aggregator.needsCount += doc.needs.length }'
    def key = new BasicDBObject()
    key.put("name", true)
    def initial = new BasicDBObject()
    initial.put ("needsCount", 0)

    def maxNeeds = 0
    def needyPets = []
    dbPets.group(key, new BasicDBObject(), initial, reduce).each {
      if (maxNeeds < it['needsCount']) {
        maxNeeds = it['needsCount']
        needyPets = []
        needyPets += it['name']
      } else if (maxNeeds == it['needsCount']) {
        needyPets += it['name']
      }
    }

    def needyPet = needyPets

    [petsNeedingCount: dbPets.find([needs: petsNeed]).count(), petsNeed: petsNeed, mostNeedyPet: needyPet]
  }

}

【问题讨论】:

  • 这有什么可怕的——性能?
  • 实施。噪音太大了new BasicDBObject().put 现在我正在查看它甚至会变得更好。此外,获取组查询的最大值将是内存操作。如果这是数百万个项目怎么办?我希望这一切都发生在数据库级别。

标签: java groovy mongodb


【解决方案1】:

应该可以将整个方法改成这个(但我没有 MongoDB 来测试它)

def index = {
  def petsNeed = 'a walk'

  def reduce = 'function(doc, aggregator) { aggregator.needsCount += doc.needs.length }'

  def key     = [ name: true    ] as BasicDBObject
  def initial = [ needsCount: 0 ] as BasicDBObject

  def allPets = dbPets.group( key, new BasicDBObject(), initial, reduce )
  def maxNeeds = allPets*.needsCount.collect { it as Integer }.max()
  def needyPet = allPets.findAll { maxNeeds == it.needsCount as Integer }.name

  [petsNeedingCount: dbPets.find([needs: petsNeed]).count(), petsNeed: petsNeed, mostNeedyPet: needyPet]
}

【讨论】:

  • 这确实是一种更时髦的代码编写方式。有一个小错误。就匹配原始代码 sn-p 的行为而言,您需要额外的一行。 needyPet = needyPet.collect { it['name'] } 只在序列中包含有需要的宠物的名字。话虽如此,这仍然是一种糟糕的方式,你不觉得吗?你完全在记忆中?我可以在控制台上完全使用带有sortlimit 之类的javascript 在数据库端执行此操作。我真正想要的是 groovy 代码中的 sortlimit 功能。
  • 啊,是的,现在修复了错误 ;-) 是的,我同意这一切都在内存中,所以可能有问题......我希望你在发布问题时说这是你的问题不过……为什么不直接通过 api 执行你在命令行上执行的查询呢?
  • 你是什么意思?通过"""...""".exec()?这似乎很hacky。有没有一种通过 Java 执行直接命令的高效方式?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
  • 2021-07-21
相关资源
最近更新 更多