我是MongoDB的新手,我正在做一些练习。特别是我被this exercise困住了,我在这里报告了这个问题:
鉴于文件"餐厅"的以下结构:
{
"_id" : ObjectId("5704adbc2eb7ebe23f582818"),
"address" : {
"building" : "1007",
"coord" : [
-73.856077,
40.848447
],
"street" : "Morris Park Ave",
"zipcode" : "10462"
},
"borough" : "Bronx",
"cuisine" : "Bakery",
"grades" : [
{
"date" : ISODate("2014-03-03T00:00:00Z"),
"grade" : "A",
"score" : 2
},
{
"date" : ISODate("2013-09-11T00:00:00Z"),
"grade" : "A",
"score" : 6
},
{
"date" : ISODate("2013-01-24T00:00:00Z"),
"grade" : "A",
"score" : 10
},
{
"date" : ISODate("2011-11-23T00:00:00Z"),
"grade" : "A",
"score" : 9
},
{
"date" : ISODate("2011-03-10T00:00:00Z"),
"grade" : "B",
"score" : 14
}
],
"name" : "Morris Park Bake Shop",
"restaurant_id" : "30075445"
}
写一个MongoDB查询来查找那些餐厅的ID,名称和等级,其中第二级元素数组包含等级" A"在ISODate" 2014-08-11T00:00:00Z"得分9。
我写了这个查询:
db.restaurants.find(
{
'grades.1': {
'score': 'A',
'grade': 9,
'date' : ISODate("2014-08-11T00:00:00Z")
}
},
{
restaurant_id: 1,
name: 1,
grades: 1
});
哪个不行。 提供的解决方案如下:
db.restaurants.find(
{ "grades.1.date": ISODate("2014-08-11T00:00:00Z"),
"grades.1.grade":"A" ,
"grades.1.score" : 9
},
{"restaurant_id" : 1,"name":1,"grades":1}
);
我的问题是:
grades.1
部分?grades.1
是文档对象?如果它可以帮助回答我的问题,我正在使用MongoDB shell version: 3.2.4
修改:
由于this question,我找到了问题2的答案。
特别是我发现顺序很重要。实际上,如果我执行以下查询,我会得到一个有效的结果:
db.restaurants.find({'grades.1': {'date': ISODate("2014-08-11T00:00:00Z"), 'grade':'A', score:9}}, {restaurant_id:1, name:1, grades:1})
请注意,此查询仅适用于所有子文档""字段"指定,并以相同的顺序指定。
答案 0 :(得分:2)
不是真的。但也许可以解释一下你能做什么"做:
db.junk.find({
"grades": {
"$elemMatch": {
"date" : ISODate("2014-03-03T00:00:00Z"),
"grade" : "A",
"score" : 2
}
},
"$where": function() {
var grade = this.grades[0];
return (
grade.date.valueOf() == ISODate("2014-03-03T00:00:00Z").valueOf() &&
grade.grade === "A" &&
grade.score ==== 2
)
}
})
$elemMatch
允许你缩短一点,但它不是" nth"数组的元素。为了进一步缩小范围,您需要使用$where
子句来检查" nth"数组元素,以查看是否所有值都匹配。
db.junk.aggregate([
{ "$match": {
"grades": {
"$elemMatch": {
"date" : ISODate("2014-03-03T00:00:00Z"),
"grade" : "A",
"score" : 2
}
}
}},
{ "$redact": {
"$cond": {
"if": {
"$let": {
"vars": { "grade": { "$arrayElemAt": [ "$grades", 0 ] } },
"in": {
"$and": [
{ "$eq": [ "$grade.date", ISODate("2014-03-03T00:00:00Z") ] },
{ "$eq": [ "$grade.grade", "A" ] },
{ "$eq": [ "$grade.score", 2 ] }
]
}
}
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
您也可以使用.aggregate()
使用$redact
执行相同的逻辑操作。它运行得更快一些,但现在基本的事实应该是清楚的。
因此使用"dot notation"指定" nth"数组中每个元素的位置就像你已经完成的那样是最有效的"简短的"写这个的方式。你不能让它更短或更好。
您的另一种尝试是寻找"文件"在"grades.1"
内符合完全您提供的文档条件。如果出于任何原因,那些不是唯一字段,或者它们确实在"不同的顺序"在存储的文档中,这样的查询条件不会匹配。