使用Spring Data Mongodb,是否可以获得字段的最大值而无需拉动和迭代整个集合?

时间:2012-03-29 21:35:26

标签: mongodb spring-data spring-data-mongodb nosql

使用mongoTemplate.find(),我指定一个查询,我可以使用.limit().sort()

.limit()会返回Query个对象
.sort()会返回Sort个对象

鉴于此,我可以说Query()。limit(int).sort(),但这不执行所需的操作,它只是对有限的结果集进行排序。

我无法调用Query()。sort()。limit(int),因为.sort()返回一个Sort()

所以使用Spring Data,我如何执行mongoDB shell中显示的以下内容?也许有办法传递一个我还没有找到的原始查询?

如果需要,我可以扩展Paging界面......似乎没有任何帮助。谢谢!

> j = { order: 1 }
{ "order" : 1 }
> k = { order: 2 }
{ "order" : 2 }
> l = { order: 3 }
{ "order" : 3 }
> db.test.save(j)
> db.test.save(k)
> db.test.save(l)
> db.test.find()
{ "_id" : ObjectId("4f74d35b6f54e1f1c5850f19"), "order" : 1 }
{ "_id" : ObjectId("4f74d3606f54e1f1c5850f1a"), "order" : 2 }
{ "_id" : ObjectId("4f74d3666f54e1f1c5850f1b"), "order" : 3 }
> db.test.find().sort({ order : -1 }).limit(1)
{ "_id" : ObjectId("4f74d3666f54e1f1c5850f1b"), "order" : 3 }

4 个答案:

答案 0 :(得分:3)

通常情况下,使用聚合SQL查询完成的事情可以在NoSQL存储中以(至少)三种方式进行处理:

  • 使用Map / Reduce。这实际上是通过所有记录,但更优化(适用于多个线程,并在群集中)。这是MongoDB的map/reduce tutorial

  • 预先计算每个插入物的最大值,并单独存储。因此,无论何时插入记录,都要将其与之前的最大值进行比较,如果更高,则更新数据库中的最大值。

  • 获取内存中的所有内容并在代码中进行计算。这是最微不足道的解决方案。它可能适用于小型数据集。

选择一个而不是另一个取决于您对此最大值的使用。如果很少执行,例如对于某些角落报告,您可以使用map / reduce。如果经常使用,则存储当前最大值

答案 1 :(得分:2)

您可以在sping-data-mongodb中执行此操作。如果排序字段被索引(或@Id字段),Mongo将优化排序/限制组合。这会产生非常快的O(logN)或更好的结果。否则它仍然是O(N)而不是O(N * logN),因为它将使用top-k算法并避免全局排序(mongodb sort doc)。这来自Mkyong's example但是我做了先排序并将限制设置为一秒。

Query query = new Query();
query.with(new Sort(Sort.Direction.DESC, "idField"));
query.limit(1);
MyObject maxObject = mongoTemplate.findOne(query, MyObject.class);

答案 2 :(得分:1)

据我所知,Mongo完全支持排序然后限制:见http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order

通过获取最大/分钟地图缩减将会非常缓慢,应该不惜一切代价避免。

我对Spring Data一无所知,但我可以推荐Morphia来帮助查询。否则,Java驱动程序的基本方法是:

DBCollection coll = db.getCollection("...");

DBCursor curr = coll.find(new BasicDBObject()).sort(new BasicDBObject("order", -1))
.limit(1);

if (cur.hasNext())
  System.out.println(cur.next());

答案 3 :(得分:0)

使用聚合$ max。 由于$ max是仅在$ group阶段可用的累加器运算符,因此您需要做一个技巧。 在组运算符中使用任何常量作为_id 让我们以Mongodb site中给出的例子 -

为例

使用以下文档考虑销售集合:

{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
{ "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
{ "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }

如果您想了解所有商品的最高价格。

db.sales.aggregate(
   [
     {
       $group:
         {
           _id: "1", //** This is the trick
           maxPrice: { $max: "$price" }
         }
     }
   ]
)

请注意" _id"的值 - 它是" 1"。你可以把任何常数......