该$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})
>
Run Code Online (Sandbox Code Playgroud)
编辑(响应下面的答案)
使用下面答案中建议的列表会阻止我找到所需的元素。例如,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
Run Code Online (Sandbox Code Playgroud)
对于子文档,没有完全等同于 $in 的内容。您可以将 $exists 查询运算符与 $or 结合使用:
db.stuff.find({$or:[
{'dic.b': {$exists: true}},
{'dic.c': {$exists: true}}
]})
Run Code Online (Sandbox Code Playgroud)
但是,推荐的方法是更改架构,以便将键和值更改为{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}]}
])
Run Code Online (Sandbox Code Playgroud)
然后您可以使用 $in 查找具有某些键的文档:
db.stuff.find({'dic.key': {$in: ['a', 'b']}})
Run Code Online (Sandbox Code Playgroud)
这个新模式的特别好处是您可以为 $in 查询使用索引:
db.stuff.createIndex({'dic.key': 1})
Run Code Online (Sandbox Code Playgroud)
正如您在上面指出的那样,一个缺点是简单的元素访问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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1724 次 |
| 最近记录: |