查询以匹配数组的第n个文档
Query to Match on nth Document of an Array
我是MongoDB的新手,我正在做一些练习。特别是我在这个练习中遇到了困难,我在这里报告了这个问题:
文件"Restaurant"的结构如下:
{
"_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查询,为那些等级数组的第二个元素包含等级"a"并且在ISODate"2014-08-11T00:00Z"上得分为9的餐厅查找餐厅Id、名称和等级。
我写了这个查询:
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
编辑:
多亏了这个问题,我找到了问题2的答案。
特别是,我发现顺序很重要。事实上,如果我执行以下查询,我会得到一个有效的结果:
db.restaurants.find({'grades.1': {'date': ISODate("2014-08-11T00:00:00Z"), 'grade':'A', score:9}}, {restaurant_id:1, name:1, grades:1})
请注意,此查询之所以有效,是因为所有子文档的"字段"都已指定,并且它们的指定顺序相同。
不是。但也许可以解释一下你"能"做什么:
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
允许您稍微缩短,但它不是数组的"第n"个元素。为了进一步缩小范围,您需要使用$where
子句来检查"第n个"数组元素,以查看所有值是否匹配。
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
执行相同的逻辑。它运行得有点快,但基本事实现在应该很清楚了。
因此,使用"点表示法"为数组中的每个元素指定"第n个"位置,就像您已经做过的那样是最有效和"简短"的编写方法。你不能把它做得更短或更好。
您的另一个尝试是在"grades.1"
中查找与您提供的文档条件完全匹配的"文档"。如果由于任何原因,这些字段不存在,或者它们在存储的文档中确实处于"不同的顺序",则这样的查询条件将不匹配。
相关文章:
- 返回一个关联数组,而不是mongoose中的文档数组
- 如何获取文档数组中元素的计数-MongoDB
- MongoDB findAndModify:>>>查找和更新文档数组中的对象
- 如何在猫鼬.js子文档数组中定义实例方法
- 通过node-js脚本将文档数组插入mongodb中的数据库时出现问题
- 通过 Meteor / Mongo 返回子文档数组
- Meteor:更新文档数组中的嵌套对象
- 通过Javascript中的JSON文档数组&使用KnockoutJS的JQuery
- 如何使用另一个文档数组中的id对光标进行排序
- 将字段插入子文档数组中.意外行为
- 如何从JSON文档数组中提取字段数组
- 如何在Mongodb中返回符合给定条件的子文档数组
- 按筛选的子文档数组元素计数排序
- 将新条目推入mongoDB文档数组
- Meteor AutoForm:如何用子文档数组更新模式值
- 我如何将文档数组更改为MongoDB shell中的值数组
- Mongodb:聚合子文档数组的值
- IBM worklight JSON存储删除文档数组
- 循环一个嵌入文档数组,将新值推入一个字段
- 插入到MongoDB文档数组的前面,没有$position和$each