mongodb$elemMatch需要一个查询条件

mongodb$elemMatch需要一个查询条件,mongodb,null,Mongodb,Null,我在Mongo(3.4.10)中有一些带有嵌套数组的文档: 我尝试了一些查询,包括使用$elemMatch和不使用: > db.test.find({'a.b':{$ne:null}}) { "a" : [ ] } { "a" : [ { "b" : [ ] } ] } { "a" : [ { "b" : [ { "c" : 1 } ] } ] } { "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] } 及 及 缔约国指出: 如果在$el

我在Mongo(3.4.10)中有一些带有嵌套数组的文档:

我尝试了一些查询,包括使用
$elemMatch
和不使用:

> db.test.find({'a.b':{$ne:null}})
{ "a" : [ ] }
{ "a" : [ { "b" : [ ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 } ] } ] }
{ "a" : [ { "b" : [ { "c" : 1 }, { "d" : 1 } ] } ] }

缔约国指出:

如果在
$elemMatch
表达式中仅指定一个
条件,则无需使用
$elemMatch


但是这些查询都返回不同的结果。我想知道这是为什么。我还想知道这些查询选择的确切目的是什么,因为在试验和阅读了有关数组查询和
$elemMatch
的文档后,我还不太清楚,第一个查询将返回符合条件或没有
b
字段的文档:

$ne选择字段值不相等的文档 (即!=)设置为指定值这包括不需要的文档 包含字段。

在第二个查询中,在验证条件之前,元素应该存在。如果没有元素,则不会返回文档:

$elemMatch运算符匹配包含数组字段的文档 至少有一个与所有指定查询匹配的元素 标准


我相信$elemMatch文档中有一点错误-他们应该指出文档中应该存在目标字段,以获得完全相同的结果。

第一个查询将返回符合条件或没有
b
字段的文档:

$ne选择字段值不相等的文档 (即!=)设置为指定值这包括不需要的文档 包含字段。

在第二个查询中,在验证条件之前,元素应该存在。如果没有元素,则不会返回文档:

$elemMatch运算符匹配包含数组字段的文档 至少有一个与所有指定查询匹配的元素 标准


我相信$elemMatch文档中有一点错误-他们应该指出文档中应该存在目标字段以获得完全相同的结果。

我已经创建了一个测试数据库,下面是我对每个输出的逐行解释

问题1 显示:

{ "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" : [ ] } ] } // 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" : [ { "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" : [ {  }, { "b" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ ] } // no elements, $elemMatch needs at least one element that matches
{ "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
第一种情况见

这两个未显示的文档没有多大意义。它们都有一个被
{$ne:null}
接受的元素,这将使整个文档被接受

不幸的是,正如我担心的那样,Mongo只需简单地运行
find({'a.b':{$eq:null}})
(),然后获取所有未列出的项目,并将它们返回给
find({'a.b':{$ne:null}})

尝试运行
find({'a.b':{$not{$eq:null}}})
自己查看。这场灾难是基于“不相等”是“相等”的反义词的想法,当单个true元素使整个文档为true时,这是不正确的(例如
any(x!=3)
!any(x==3)

问题2 显示:

{ "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" : [ ] } ] } // 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" : [ { "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" : [ {  }, { "b" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ ] } // no elements, $elemMatch needs at least one element that matches
{ "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
只考虑其
a
在这里)不可用的情况。只有这样,它才会应用谓词

因此,它甚至从不考虑
{“a”:[]}
,因为它是一个空数组。在本例中,我们看到在所有剩余文档中,至少有一个数组元素
a
存在非空
b
字段,因此这些字段是可以接受的

问题3 显示:

{ "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" : [ ] } ] } // 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" : [ { "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" : [ {  }, { "b" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ ] } // no elements, $elemMatch needs at least one element that matches
{ "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
只考虑其
为非空数组的情况,但此处
a.b
而不是
a
。未显示的三个文档不符合此初始标准,因此从未进行过测试。其余三个文档都是非空数组,包含多个非空元素,因此都被接受

结论:
$elemMatch
文档确实具有误导性,它们应该说明:

如果在
$elemMatch
表达式中仅指定一个
条件,则只要
是非空数组,就不需要使用
$elemMatch

即使这样,问题1和问题3也不完全一致。这是因为
$elemMatch
似乎强制
{$ne:null}
a.b
()的每个元素计算一次,而排除它似乎一次将
{$ne:null}
应用于整个
a.b


我认为Mongo应该始终在元素方面应用
ne
element,否则就好像是一个bug。这件事我已经存档了。请投赞成票来解决这个问题。

我已经创建了一个测试数据库,下面是我对每个输出的逐行解释

问题1 显示:

{ "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" : [ ] } ] } // 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" : [ { "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" : [ {  }, { "b" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ ] } // no elements, $elemMatch needs at least one element that matches
{ "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
第一种情况见

这两个未显示的文档没有多大意义。它们都有一个被
{$ne:null}
接受的元素,这将使整个文档被接受

不幸的是,正如我担心的那样,Mongo只需简单地运行
find({'a.b':{$eq:null}})
(),然后获取所有未列出的项目,并将它们返回给
find({'a.b':{$ne:null}})

尝试运行
find({'a.b':{$not{$eq:null}}})
自己查看。这场灾难是基于“不相等”是“相等”的反义词的想法,当单个true元素使整个文档为true时,这是不正确的(例如
any(x!=3)
!any(x==3)

问题2 显示:

{ "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" : [ ] } ] } // 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" : [ { "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" : [ {  }, { "b" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ { "b" : [ { "c" : 1 } ] }, { "d" : 1 } ] } // find({'a.b':null}) matches, so discard
{ "a" : [ ] } // no elements, $elemMatch needs at least one element that matches
{ "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
只考虑其
a
在这里)不可用的情况。只有这样,它才会应用谓词

因此,它甚至从不考虑
{“a”:[]}
,因为它是空的