我在Mongo(3.4.10)中有一些嵌套数组的文档:
> db.test.find()
{ "a" : [ ] } // doc number 1
{ "a" : [ { "b" : [ ] } ] } // doc number 2
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] } // doc number 3
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] } // doc number 4
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // doc number 5
{ "a" : [ { }, { "b" : 1 } ] } // doc number 6
我尝试了一些问题,包括$elemMatch
和没有:
> db.test.find({'a.b':{$ne:null}})
{ "a" : [ ] }
{ "a" : [ { "b" : [ ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] }
和
> db.test.find({a:{$elemMatch:{b:{$ne:null}}}})
{ "a" : [ { "b" : [ ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] }
{ "a" : [ { }, { "b" : 1 } ] }
和
> db.test.find({'a.b':{$elemMatch:{$ne:null}}})
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] }
docs表示:
如果您在
<query>
表达式中仅指定一个$elemMatch
条件,则无需使用$elemMatch
。
但这些查询都会返回不同的结果。我想知道为什么会这样。我还想知道这些查询究竟选择了什么,因为在尝试和阅读有关数组查询和$elemMatch
的文档之后,我无法完成它。
答案 0 :(得分:1)
第一个查询将返回文档 匹配条件或没有b
字段:
$ ne选择字段值不相等的文档 (即!=)到指定的值。 这包括没有的文件 包含该字段。
在第二个查询中,元素应该在验证条件之前存在。如果没有元素,则不会返回文档:
$ elemMatch运算符匹配包含数组字段的文档 至少一个元素与所有指定的查询匹配 标准。
我认为这是$ elemMatch文档中的一个小错误 - 他们应该指出文档中应该存在目标字段以获得完全相同的结果。
答案 1 :(得分:1)
我已经创建了一个测试数据库,这是我对每个输出的逐行说明。
db.test.find({'a.b':{$ne:null}})
显示:
{ "a" : [ ] } // doesn't contain b, so valid (mentioned by Sergey, see $ne docs)
{ "a" : [ { "b" : [ ] } ] } // has non-null b
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] } // has non-null b
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] } // has non-null b
未显示:
{ "a" : [ { }, { "b" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // find({'a.b':null}) matches, so discard
第一个案例见$ne
docs。
这两个未显示的文件没有多大意义。它们都有{$ne:null}
接受的单个元素,这应该使整个文档被接受。
不幸的是,正如我所担心的那样,Mongo采用简单运行find({'a.b':{$eq:null}})
(source here)的快捷方式,然后列出所有不的项目并将其返回给{{ 1}}。
尝试运行find({'a.b':{$ne:null}})
自己查看。这种不幸是基于“不等于”是“相等”的倒数的想法,当单个真实元素使整个文档成立时,这是不正确的(例如find({'a.b':{$not {$eq:null}}})
与{{1}不同}})。
any(x!=3)
显示:
!any(x==3)
未显示:
db.test.find({a:{$elemMatch:{b:{$ne:null}}}})
这里的诀窍是{ "a" : [ { "b" : [ ] } ] } // non-null b
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] } // non-null b
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] } // non-null b
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // one element has non-null b
{ "a" : [ { }, { "b" : 1 } ] } // one element has non-null b
仅考虑其{ "a" : [ ] } // no elements, $elemMatch needs at least one element that matches
($elemMatch
此处)为an array of one or more elements的情况。只有这样才会应用谓词。
因此它甚至从未考虑<field>
,因为它是一个空数组。在这种情况下,我们看到在所有剩余文档中至少有一个数组a
的元素存在非空{ "a" : [ ] }
字段,因此接受这些字段。
b
显示:
a
未显示:
db.test.find({'a.b':{$elemMatch:{$ne:null}}})
这里的诀窍是{ "a" : [ { "b" : [ { "c" : 1 } ] } ] } // a.b an array with 1+ elements
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] } // a.b an array with 1+ elements
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // a.b an array with 1+ elements
仅考虑其{ "a" : [ ] } // a.b not an array with 1+ elements
{ "a" : [ { "b" : [ ] } ] } // a.b not an array with 1+ elements
{ "a" : [ { }, { "b" : 1 } ] } // a.b not an array with 1+ elements
是非空数组的情况,但此处$elemMatch
为<field>
而不是<field>
}。未显示的三个文档不符合此初始标准,因此从未进行过测试。其余三个文档都是非空数组,超过1个非空元素,所以都被接受了。
a.b
文档确实具有误导性,他们应说明:
如果您在
a
表达式中仅指定一个$elemMatch
条件,则只要<query>
为非$elemMatch
,就不需要使用$elemMatch
, -empty数组。
即便如此,查询1和3也不一致。这是因为<field>
似乎强制$elemMatch
每个元素{$ne:null}
(source here)被评估一次,而排除它似乎将a.b
应用于整个{$ne:null}
暂时a.b
。
我认为Mongo应该始终以元素方式应用ne
,否则看起来像是一个bug。我已就此提出a Jira Issue in Mongo。请将其投票以解决此问题。