MongoDB使用$并使用切片和匹配

时间:2018-01-23 17:51:49

标签: mongodb-query spring-data

我正在使用spring数据包中的@Query,我想查询文档中数组的 last 元素。

例如,数据结构可能是这样的:

{
   name : 'John',
   scores: [10, 12, 14, 16]
},
{
   name : 'Mary',
   scores: [78, 20, 14]
},

所以我构建了一个查询,但它抱怨“错误消息'未知运算符:$ slice'在服务器上”

查询的$ slice部分,当单独运行时,很好:

db.getCollection('users').find({}, {scores: { $slice: -1 })

但是,只要我将它与更复杂的检查结合起来,就会出现上述错误。

db.getCollection('users').find{{"$and":[{ } , {"scores" : { "$slice" : -1}} ,{"scores": "16"}]})

此查询将返回最后得分为16的用户列表,在我的示例中,John将被退回但不会返回Mary。

我把它放入一个标准的mongo查询(调试东西),但理想情况下我需要它进入一个spring-data @query构造 - 它们应该非常相似。

有没有这样做,而不诉诸手摇java调用?除了标准查询之外,我没有看到@Query的大量文档。

如链接帖子所述,它指的是聚合,它如何与@Query一起使用,加上其中一个主要答案使用$ where,这效率很低。

1 个答案:

答案 0 :(得分:0)

遗憾的是,问题的一般方法是数据,尽管@ Veeram的回答是正确的,但这意味着你没有点击索引。这是一个当然你有非常大的数据集的问题,你会看到不断减少的返回时间。这是$ where,$ arrayElemAt无法帮助你。他们必须预处理数据,这意味着完整的集合扫描。我们用这些结构分析了几个查询,它们涉及“COLSCAN”。

理想情况下,解决方案是创建包含最后一项的字段,例如:

@Component
public class ScoreListener extends AbstractMongoEventListener<Scores>

你可以创建一个监听器来维护它,如下所示:

@Override
public void onBeforeConvert(BeforeConvertEvent<Scores> event) {
      // process any score and set lastScore
}

然后,您可以嗅探数据并进行任何更新:

@CompoundIndex(name = "lastScore", def = "{"
        + "'lastScore': 1"
        + " }")

不要忘记更新索引(!):

if(locationList.size > 0){ ///Set adapter to Recycler view

虽然这确实包含了轻微重复数据的缺点,但在当前的Mongo(3.4)中,这实际上是执行此操作的唯一方法,并且在搜索机制中包含索引。速度差异很大,从接近一分钟的响应时间到毫秒。

在Mongo 3.6中可能有更好的方法,但是我们已经修复了这个版本,所以这必须是我们的解决方案。