使用$ vs使用$ slice投影数组

时间:2014-02-12 10:12:38

标签: mongodb mongodb-query

我有一个如下集合: -

{ "_id" : 1, "grades" : [ 70, 87, 90 ] }
{ "_id" : 2, "grades" : [ 90, 88, 92 ] }

我正在使用以下查询: -

db.students.find( { semester: 1, grades: { $gte: 85 } },
                  { "grades.$": 1 } )

我得到的结果为: -

{ "_id" : 1, "grades" : [ 87 ] }
{ "_id" : 2, "grades" : [ 90 ] }

现在我的问题是,当我在字段等级上使用$ gte时,它将检查数组的任何元素是否与条件匹配,如果是,则返回文档。那么为什么我得到第一个文档的输出为87而不是70.我知道我们已经指定了一个相等的条件“grade:{$ gte:85}”但是它已经返回了我的完整文档并预测了第一个字段。那么为什么87是输出?

1 个答案:

答案 0 :(得分:1)

  

那么为什么我得到第一个文件的输出为87而不是70。

因为你特意要求它。这正是positional projection operator $的用途:它返回与查询匹配的第一个元素,因此投影grades.$ : 1将返回一个包含第一个且仅包含第一个的数组数组中符合标准的元素,即大于或等于85的第一个元素。

它仍然是一个数组可能会令人恼火 - 毕竟,因为它总是只有一个元素,所以它们可以为你提供像grades:87这样的值。这是MongoDB中的一种模式:除非您使用聚合框架,否则它不会修改数据结构,从而可以更轻松地将查询结果映射到您的静态类型语言。

如果你想改为使用整个数组,根本就不需要投影:

db.students.find( { semester: 1, grades: { $gte: 85 } } )
{ "_id" : 1, semester: 1, "grades" : [  70,  87,  90 ] }
{ "_id" : 2, semester: 1, "grades" : [  90,  88,  92 ] }

如果您只想要数组中的第一个元素(而不是第一个匹配的元素),则可以使用$slice

db.students.find({semester: 1, grades: { $gte: 85 } },{ "grades": {$slice : 1}});
{ "_id" : 1, semester: 1, "grades" : [  70 ] }
{ "_id" : 2, semester: 1, "grades" : [  90 ] }