如果我有以下文件:
{a: {x:1}} // without array
{a: [{x:1}]} // with array
有没有办法查询{'a.x':1}
将返回第一个而不是第二个? IE,我想要a.x为1的文档,而a不是数组。
答案 0 :(得分:5)
请注意future version of MongoDB would incorporate the $isArray
aggregation expression。在此期间......
...以下代码可以解决问题,因为$elemMatch
运算符只匹配具有数组字段的文档:
import os
import glob
contents = []
json_dir_name = "/path/to/json/dir"
json_pattern = os.path.join(json_dir_name,'*.json'
file_list = glob.glob(json_pattern)
for file in file_list:
contents.append(read(file))
鉴于该数据集:
> db.test.find({"a.x": 1, "a": {$not: {$elemMatch: {x:1}}}})
它将返回:
> db.test.find({},{_id:0})
{ "a" : { "x" : 1 } }
{ "a" : [ { "x" : 1 } ] }
{ "a" : [ { "x" : 0 }, { "x" : 1 } ]
请注意,这应被视为短期解决方案。 MongoDB团队非常谨慎地确保> db.test.find({"a.x": 1, "a": {$not: {$elemMatch: {x:1}}}}, {_id:0})
{ "a" : { "x" : 1 } }
和[{x:1}]
行为相同(请参阅dot-notation或$type
for arrays)。因此,应考虑在将来的某个时刻,{x:1}
可能会更新(请参阅JIRA问题SERVER-6050)。与此同时,也许值得考虑修复您的数据模型,因此不再需要区分包含一个子文档的数组和一个裸子文档。
答案 1 :(得分:5)
您可以通过添加第二个术语来确保a
没有元素。当a
是普通子网时,第二项将始终为真,当a
为数组时,总是为假(否则第一项将不匹配)。
db.test.find({'a.x': 1, 'a.0': {$exists: false}})