下面是一个小型的MongoDB数据库:
> db.sss.find().pretty()
{
"_id" : ObjectId("543f53b8711761110238be74"),
"name" : "A",
"pos" : 828288,
"s_type" : 1,
"sub_name" : "B01",
"type" : "Test",
"x_type" : 7,
"chr" : [
{
"5" : "C"
},
{
"6" : "T"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be75"),
"name" : "A",
"pos" : 171878,
"s_type" : 3,
"sub_name" : "B01",
"type" : "Test",
"x_type" : 8,
"chr" : [
{
"5" : "C"
},
{
"6" : "T"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be76"),
"name" : "A",
"pos" : 871963,
"s_type" : 3,
"sub_name" : "B01",
"type" : "Test",
"x_type" : 9,
"chr" : [
{
"5" : "A"
},
{
"6" : "G"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be77"),
"name" : "A",
"pos" : 1932523,
"s_type" : 1,
"sub_name" : "B01",
"type" : "Test",
"x_type" : 10,
"chr" : [
{
"4" : "T"
},
{
"5" : "A"
},
{
"6" : "X"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be78"),
"name" : "A",
"pos" : 667214,
"s_type" : 1,
"sub_name" : "B01",
"type" : "Test",
"x_type" : 14,
"chr" : [
{
"4" : "T"
},
{
"5" : "G"
},
{
"6" : "G"
}
]
}
以上脚本创建了上述数据库:
from pymongo import MongoClient
from collections import defaultdict
db = MongoClient().test
sDB = db.sss
r = [["Test", "A", "B01", 828288, 1, 7, 'C', 5],
["Test", "A", "B01", 828288, 1, 7, 'T', 6],
["Test", "A", "B01", 171878, 3, 8, 'C', 5],
["Test", "A", "B01", 171878, 3, 8, 'T', 6],
["Test", "A", "B01", 871963, 3, 9, 'A', 5],
["Test", "A", "B01", 871963, 3, 9, 'G', 6],
["Test", "A", "B01", 1932523, 1, 10, 'T', 4],
["Test", "A", "B01", 1932523, 1, 10, 'A', 5],
["Test", "A", "B01", 1932523, 1, 10, 'X', 6],
["Test", "A", "B01", 667214, 1, 14, 'T', 4],
["Test", "A", "B01", 667214, 1, 14, 'G', 5],
["Test", "A", "B01", 667214, 1, 14, 'G', 6]]
for i in r:
sDB.update({'type': i[0],
'name': i[1],
'sub_name': i[2],
'pos': i[3],
's_type': i[4],
'x_type': i[5]},
{"$push": {"chr":{str(i[7]): i[6]} }}, True)
我开始针对以下条件编写查询:
x_type:7
和x_type:9
是正确的,因为chr.5
和chr.6
具有不同的字符,而且它们都没有字符X. x_type:8
是正确的,但超出范围(200000到2000000)x_type:10
无效,因为chr.6
包含X x_type:14
无效,因为chr.5
和chr.6
具有相同的字符但是,我没有通过以下草稿查询得到我想要的内容:
> db.snps.find({"pos": {$gte: 200000, $lt: 2000000}}, {"chr":{$elemMatch:{"6":{$ne: "X"}}}}).pretty()
{
"_id" : ObjectId("543f53b8711761110238be74"),
"chr" : [
{
"5" : "C"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be76"),
"chr" : [
{
"5" : "A"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be77"),
"chr" : [
{
"4" : "T"
}
]
}
{
"_id" : ObjectId("543f53b8711761110238be78"),
"chr" : [
{
"4" : "T"
}
]
}
我做错了什么?
答案 0 :(得分:1)
您似乎在使用错误的$elemMatch
形式,因为您使用的是“投影”形式,用于选择数组中第一个匹配条件你提供的。您在此处指定的唯一“查询”条件是“pos”值落在请求的范围内。
如果您想要的是两者,则条件存在于文档在该范围内具有“pos”值并且“chr.6”中没有“X”值的情况。在比较数组元素的值时,final和additional子句有点棘手。但是这可以通过$where
的JavaScript评估来实现,只要只有并且总是有两个元素,这是非常简单的:
db.snps.find({
"pos": { "$gte": 200000, "$lt": 2000000 },
"chr.6": { "$ne": "X" },
"$where": "this.chr[0]['5'] != this.chr[1]['6']"
})
对于其他组合或命名元素来说有点棘手,但JavaScript评估的相同原则适用于该条件。
因此,由于仅测试数组元素的一个字段,因此您不需要$elemMatch
的查询形式,因此投影位于错误的位置。你想要一个“查询”条件,选择符合它们的文件。