5

使用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

5 回答 5

5

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

Query query = new Query();
query.with(new Sort(Sort.Direction.DESC, "idField"));
query.limit(1);
MyObject maxObject = mongoTemplate.findOne(query, MyObject.class);
于 2016-10-11T17:01:04.263 回答
3

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

  • 使用地图/减少。这有效地遍历了所有记录,但更优化(适用于多线程和集群)。这是 MongoDB 的map/reduce 教程

  • 预先计算每个插入的最大值,并将其单独存储。因此,每当您插入一条记录时,您都会将其与之前的最大值进行比较,如果它更大,则更新数据库中的最大值。

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

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

于 2012-03-29T21:40:54.423 回答
1

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

通过map reduce获得最大/最小将非常慢,应该不惜一切代价避免。

我对 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());
于 2012-03-30T19:56:08.027 回答
0

由于第一个答案是正确的,但代码已过时,我正在回复一个对我有用的类似解决方案:

Query query = new Query();
query.with(Sort.by(Sort.Direction.DESC, "field"));
query.limit(1);
Entity maxEntity = mongoTemplate.findOne(query, Entity.class);
于 2021-10-01T07:13:09.910 回答
0

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

考虑包含以下文档的销售集合:

{ "_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”。你可以把任何常数...

于 2015-11-24T14:21:23.437 回答