arrays - MongoDB:通过对嵌套文档数组执行的范围过滤器查找文档
问题描述
考虑将分数收集为嵌套文档数组的文档集合,如下所示(我使用的是 MongoDb 4.2):
{
"scores" : [
{ "value" : 2 },
{ "value" : 3 },
{ "value" : 4 }
]
}, {
"scores" : [
{ "value" : 8 },
{ "value" : 9 },
{ "value" : 10 }
]
}, {
"scores" : [
{ "value" : 7 },
{ "value" : 7 },
{ "value" : 10 }
]
}
现在考虑以下用例:“给我所有只包含 [X, Y] 范围内分数的文档”。换句话说,请过滤掉至少有一个值不在 [XY] 范围内的文档。旁注:在实际数据中,分数是实数,所以在这里做一些 $in 查询将无济于事。
让我们考虑三个范围:
- 范围 [8, 10](一个文档应该匹配)
- 范围 [0, 1](0 文档匹配)。
- 范围 [5, 6](0 文档匹配)。
作为 mongo 的非专家,我的第一次尝试是这样做:
db.test.find({
$and: [
{ "scores.value": {$gte: 8}},
{ "scores.value": {$lte: 10}}
]
})
- 案例 [8, 10]:2 条记录。
- 案例 [0, 1] : 0 条记录
- 案例 [5, 6] : 2 条记录
所以这里有一些奇怪的东西:第一个结果表明我的查询实际上返回了满足任一条件的分数(有点像 $or 而不是 $and)。但这是真的吗,我会在第二种情况下检索所有记录 [0, 1] 而不是 0。显然我在这里使用了错误的方式,但如果有人能解释我为什么,我会很高兴.
下一个查询:
db.test.find({
"scores": {
$elemMatch: {
value: {$gte: 6.5, $lte: 6.8}
}
}
})
- 案例 [8, 10]:2 条记录。
- 案例 [0, 1] : 0 条记录
- 案例 [5, 6] : 0 条记录
对于那个,一切都很好,并且按记录/预期工作,但它没有回答我原来的用例。
所以除了理解使用第一个查询发生了什么之外,有没有人知道实现我想要做的事情的方法?
解决方案
以 [8-10] 为例,正如您所提到的,您可以编写一个查询来查找至少分数不在 [8-10] 范围内的所有“坏”文档:这就是elementMatch
.
“坏”文件是(分数 < 8 或分数 > 10):
db.collection.find({
"scores": {
$elemMatch: {
$or: [ { value: { $lt: 8 }}, { value: { $gt: 10 }} ]
}
}
})
然后你可以用 a 反转条件$not
以获得你期望的结果(拒绝“坏”文件):
db.collection.find({
"scores": {
$not: {
$elemMatch: {
$or: [ { value: { $lt: 8 }}, { value: { $gt: 10 }} ]
}
}
}
})
推荐阅读
- python - 如何在使用scrapy框架进行抓取时排除已经抓取的网址
- javascript - 未捕获的类型错误:fs_1.default.readFileSync 不是函数
- processing - 使用p5.js更改处理代码并显示形状
- jmeter - 如何为相同的用户操作按顺序发送一些 api 调用和并行发送一些 api 调用
- angular - Angular 11 自定义验证
- python - 重命名符号 (F2) 返回“无结果”。
- php - 正则表达式将数据提取到数组
- python - Python/Django URL
- sharepoint-online - 使用 PnP JS Core 检索项目时使用 get() 仅返回“未定义” - 使用 items() 返回值?
- python - 根据另一列的值填充一列中的缺失值