gpt4 book ai didi

javascript - 查询以匹配数组的第 n 个文档

转载 作者:可可西里 更新时间:2023-11-01 10:23:13 26 4
gpt4 key购买 nike

我是 MongoDB 的新手,我正在用它做一些练习。特别是我卡在了 this exercise ,其中我在这里报告问题:

给定文档“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"
}

Write a MongoDB query to find the restaurant Id, name and grades for those restaurants where 2nd element of grades array contains a grade of "A" and score 9 on an ISODate "2014-08-11T00:00:00Z".

我写了这个查询:

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}
);

我的问题是:

  1. 有没有一种方法可以避免重复 grades.1 部分来编写查询?
  2. 鉴于 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})

请注意,此查询之所以有效,是因为指定了所有 子文档的“字段”,并且它们以相同的顺序指定。

最佳答案

不是真的。但也许是对您“可以”做什么的解释:

  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"
}
}}
])

您可以对 $redact 执行相同的逻辑以及使用 .aggregate()。它运行得更快一些,但现在基本的真相应该很清楚了。

所以使用 "dot notation"像您已经完成的那样为数组中的每个元素指定“第 n 个”位置最有效和“简短”的编写方法。你不能让它更短或更好。

您的另一个尝试是在 "grades.1" 中寻找与您提供的文档条件完全匹配的“文档”。如果出于任何原因,这些不是唯一字段,或者如果它们确实在存储文档中处于“不同顺序”,那么这样的查询条件不会是匹配。

关于javascript - 查询以匹配数组的第 n 个文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36443629/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com