MongoDB:使用子文档中的键查找文档

时间:2017-07-04 16:27:29

标签: mongodb

$in运算符适用于数组。

是否有词典的等价物?

以下代码创建两个测试文档,并在数组文档中查找包含所列值之一的文档,但在子文档中找不到包含相同值的文档。

> use test
> db.stuff.drop()
> db.stuff.insertMany([{lst:['a','b'],dic:{a:1,b:2}},{lst:['a','c'],dic:{a:3,c:4}}])
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("595bbe8b3b0518bcca4b1530"),
                ObjectId("595bbe8b3b0518bcca4b1531")
        ]
}
> db.stuff.find({lst:{$in:['b','c']}},{_id:0})
{ "lst" : [ "a", "b" ], "dic" : { "a" : 1, "b" : 2 } }
{ "lst" : [ "a", "c" ], "dic" : { "a" : 3, "c" : 4 } }
> db.stuff.find({dic:{$in:['b','c']}},{_id:0})
> 

编辑(以回答以下答案)

使用下面答案中建议的列表可以防止我找到所需的元素。例如,在这个问题的上面insertMany和下面的答案中执行了> x=db.stuff.findOne({lst:{$in:['b','c']}},{_id:0}) { "lst" : [ "a", "b" ], "dic" : { "a" : 1, "b" : 2 } } > x { "lst" : [ "a", "b" ], "dic" : { "a" : 1, "b" : 2 } } > x.dic.a 1 > x.dic.b 2 之后,可以用字典来完成,而不是列表(或者我错过了什么?):

eureka.instance.hostname

1 个答案:

答案 0 :(得分:4)

对于子文档,没有完全等同于$ in。您可以使用$ exists查询运算符与$或:

结合使用
db.stuff.find({$or:[
    {'dic.b': {$exists: true}},
    {'dic.c': {$exists: true}}
]})

但是,建议的方法是更改​​架构,以便将键和值更改为{key: "key", value: 123}子文档的数组:

db.stuff.insertMany([
   {dic: [{key: 'a', value: 1}, {key: 'b', value: 2}]},
   {dic: [{key: 'a', value: 3}, {key: 'c', value: 4}]}
])

然后您可以使用$ in查找包含某些键的文档:

db.stuff.find({'dic.key': {$in: ['a', 'b']}})

关于这个新架构的特别好处是你可以在$ in查询中使用索引:

db.stuff.createIndex({'dic.key': 1})

如上所述,缺点是像x.dic.a这样的简单元素访问不再有效。您需要用您的语言进行一些编码。例如。在Javascript:

> var doc = {dic: [{key: 'a', value: 3}, {key: 'c', value: 4}]}
> function getValue(doc, key) {
...   return doc.dic.filter(function(elem) {
...     return elem.key == key;
...   })[0].value;
... }
> getValue(doc, "a")
3
> getValue(doc, "c")
4