我试图从mongodb中的数组中检索一个对象。以下是我的文件:
{
"_id" : ObjectId("53e9b43968425b29ecc87ffd"),
"firstname" : "john",
"lastname" : "smith",
"trips" : [
{
"submitted" : 1407824585356,
"tripCategory" : "staff",
"tripID" : "1"
},
{
"tripID" : "2",
"tripCategory" : "volunteer"
},
{
"tripID" : "3",
"tripCategory" : "individual"
}
]
}
我的最终目标是仅在trip.submitted缺席时更新,所以我认为我可以查询并确定mongo查找行为的样子 如果我使用$和查询运算符。所以我试试这个:
db.users.find({
$and: [
{ "trips.tripID": "1" },
{ "trips": { $elemMatch: { submitted: { $exists: true } } } }
]
},
{ "trips.$" : 1 } //projection limits to the FIRST matching element
)
然后我回来了:
{
"_id" : ObjectId("53e9b43968425b29ecc87ffd"),
"trips" : [
{
"submitted" : 1407824585356,
"tripCategory" : "staff",
"tripID" : "1"
}
]
}
大。这就是我要的。 但是,当我运行此查询时:
db.users.find({
$and: [
{ "trips.tripID": "2" },
{ "trips": { $elemMatch: { submitted: { $exists: true } } } }
]
},
{ "trips.$" : 1 } //projection limits to the FIRST matching element
)
我得到与第一个相同的结果!所以我知道我的查询有些奇怪但不正确。但我不知道是什么。我在查询之间唯一改变的是" trips.tripID" :" 2" ,在我的脑海中,应该提示mongo没有返回任何结果。我的查询出了什么问题?
答案 0 :(得分:2)
如果您知道数组是按特定顺序排列的,您可以像这样引用数组中的特定索引: -
db.trips.find({"trips.0.submitted" : {$exists:true}})
或者您可以简单地在两个值上进行元素匹配:
db.trips.find({"trips" : {$elemMatch : {"tripID" : "1",
"submitted" : {$exists:true}
}}})
相比之下,您的查询正在查找文档,其中两者都是真的,而不是trip行为字段中的两个元素。
答案 1 :(得分:1)
查询的输出是正确的。您的查询要求mongo在其行程数组中返回具有给定 tripId 和字段已提交的文档。您在问题中提供的文档同时满足 tripIds 的两个条件。由于您的投影,您将获得数组 trip 中的第一个元素。
我假设您将按人名过滤记录,然后根据字段存在标准检索行程中的元素。您可以使用以下方法获得您期望的输出:
db.users.aggregate(
[
{$match:
{
"firstname" : "john",
"lastname" : "smith"
}
},
{$unwind: "$trips"},
{$match:
{
"trips.tripID": "1" ,
"trips.submitted": { $exists: true }
}
}
]
)
聚合管道的工作原理如下。第一个$match
运算符过滤一个文档(在本例中是 john smith的文档)mongodb聚合中的$unwind
运算符展开指定的数组(行程在这种情况下),实际上对与父记录相关联的子记录进行非规范化。第二个$match
运算符进一步过滤非规范化/展开的文档,以获得根据您的查询所需的文档。