【问题标题】:Find document with array that consists exclusively particular documents in MongoDB查找包含 MongoDB 中特定文档的数组的文档
【发布时间】:2016-12-11 15:11:31
【问题描述】:

我收集了 path_test 里面有 2 个文档

文档 1

{
  "_id" : 1,
  "tpc" : 5,
  "path" : [ 
    {
      "nids" : [ 0, 10, 11 ],
      "ctc" : 2
    }, 
    {
      "nids" : [ 0, 10 ],
      "ctc" : 2
    }, 
    {
      "nids" : [ 0, 10, 21 ],
      "ctc" : 1
    }
  ]
}

文档 2

{
  "_id" : 2,
  "tpc" : 5,
  "path" : [ 
    {
      "nids" : [ 0, 10, 110 ],
      "ctc" : 1
    }, 
    {
      "nids" : [ 0, 10, 11 ],
       "ctc" : 2
    }, 
    {
      "nids" : [ 0, 5 ],
      "ctc" : 2
    }
  ]
}

我想要得到的结果是带有path 数组的文档,其中所有元素都有nids,如[0, 10, *]。顺序很重要,所以[10, 0, *] 会出错。 它应该找到文档 1,但不是文档 2。希望在我开始使用 map-reduce 或聚合之前,我可以通过查询来解决这个问题。

这是我迄今为止尝试过的

查询1

db.getCollection('path_test').find( {
  "path": { $not: { $elemMatch: { "nids.0": { $nin: [0] }, "nids.1": { $nin: [10] } } } }
});

查询 2

db.getCollection('path_test').find( {
  "path.nids": { $not: { $elemMatch: { $nin: [0, 10] } } }
});

但是这两个查询都给了我只有 0 或只有 10 的结果,但我需要两者并按照确切的顺序。

这可能吗?

【问题讨论】:

  • 希望您知道这一点。 $elemMatch 将只返回一条与查询匹配的记录。
  • @Shrabanee 感谢您指出这一点。但我知道它将匹配至少一个包含该字段的元素。
  • @Shrabanee 你的建议是错误的。根据documentation$elemMatch 运算符匹配包含一个数组字段的 documents,其中至少一个元素匹配所有指定的查询条件。一般情况下它不会只返回一条记录,如果它的数组字段中至少有一个元素匹配所有指定的查询条件,它会返回记录。
  • 你想只返回那些对数组进行排序的文档吗?这背后的逻辑很难理解。

标签: arrays mongodb mongodb-query


【解决方案1】:

不是至少一个意味着没有人

查询 1

为简单起见,让我们赋值

A = "nids.0": { $ne: 0 }
B = "nids.1": { $ne: 10 }
C = { A, B }

然后

{ "path" : { $elemMatch: C } }

将查找path 数组中至少一个元素满足条件C 的文档,而

{ "path" : { $not: { $elemMatch: C } } }

将在path 数组中找到满足条件C 的元素的文档。

文档 1 和文档 2 在其 path 数组中没有满足条件 C 的元素,因此 Query1 输出包含这两个元素。如果,f.e,您添加到文档 1 的 path 数组

{ "nids": [ 1, 11, 110], "ctc" : 1 }

那么文档 1 将不会出现在查询 1 的输出中,因为这个添加的元素满足 C

查询 2

为简单起见,让我们赋值

C = { $nin: [0, 10] }

然后

{ "path.nids" : { $not: { $elemMatch: C } } }

将在path.nids 数组中找到满足条件C 的元素的文档。

path.nids 数组中的文档 1 和文档 2 具有满足条件 C 的元素,因此查询 2 输出不包含它们。如果,例如,您添加到您的收藏文件中

{ "_id" : 6, "tpc" : 5, "path" : [ { "nids" : [ 0, 10 ], "ctc" : 1 } ] }

那么它将在查询 2 的输出中,因为在 path.nids 数组中没有满足 C 的元素。

解决方案

在查询 1 中替换

{ $elemMatch: { "nids.0": { $nin: [0] }, "nids.1": { $nin: [10] } } }

{ $elemMatch: { $or: [ { "nids.0": { $ne: 0 } }, { "nids.1": { $ne: 10 } } ] } }

这个新查询将查找在path 数组中没有满足至少一个条件AB 的元素的文档。因此,它会找到文档 1,而不是文档 2(其中 "nids" : [ 0, 5 ] 不满足条件 B

注意{ $ne: 10 } 等同于{ $nin: [10] }

【讨论】:

    猜你喜欢
    • 2020-04-19
    • 2014-12-16
    • 1970-01-01
    • 2017-07-08
    • 2016-06-18
    • 2019-05-17
    相关资源
    最近更新 更多