您正在发送的查询“正确”返回文档它实际上符合您要求的条件。这是因为您正在测试的属性中“至少有一个”数组元素实际上与查询中的条件匹配。
由此我们可以推测两种可能的结果:
你的意图是只返回那里所有数组项满足条件的文件。
您的意图是“过滤”来自“文档中的数组”的条目,只返回符合条件的结果。
从这些有不同的方法。首先是实际上MongoDB中没有这样的查询操作符,它要求“所有”数组元素必须满足给定的条件,使用“常规查询”。因此,您需要以不同的形式应用逻辑。
一种这样的选择是以检查数组内容的方式使用JavaScript评估$where
。在这里你可以申请Array.every()
为了测试你的条件,除了常规的查询过滤器,因为这实际上是在做一些有用的工作。
给定的源文件,如:
/* 1 */
{
"_id" : ObjectId("5993a35be38f41729f1d6501"),
"name" : "string",
"explicitMods" : [
"+48 to Blah",
"-13% to Blah",
"12 to 18 to Blah"
]
}
/* 2 */
{
"_id" : ObjectId("5993a35be38f41729f1d6502"),
"name" : "string",
"explicitMods" : [
"12 to 18 to Blah"
]
}
如果你的意图是只返回了“文件”,它匹配的“所有”的数组元素,在发出声明:
db.myCollection.find({
"explicitMods": /\d+ to \d+/,
"$where": function() { return this.explicitMods.every(e => /\d+ to \d+/.test(e)) }
}
})
仅返回匹配文件:
{
"_id" : ObjectId("5993a35be38f41729f1d6502"),
"name" : "string",
"explicitMods" : [
"12 to 18 to Blah"
]
}
在使用的替代情况下,MongoDB的聚合框架允许使用“本地编码运算符”的表达式,这些运算符通常应用比JavaScript解释表达式更快。然而,实际上不存在$regex
等同于()的“逻辑运算符”,其适用于聚合操作,例如$redact
。
因此只可在这里采取的办法是改用$match
定期查询条件“之后的”数组元素已非规范化使用$unwind
:
db.myCollection.aggregate([
// Match "possible" documents
{ "$match": { "explicitMods": /\d+ to \d+/ } },
// unwind to denormalize
{ "$unwind": "$explicitMods" },
// Match on the "array" items now as documents
{ "$match": { "explicitMods": /\d+ to \d+/ } },
// Optionally "re-group" back to documents with only matching array items
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"explicitMods": { "$push": "$explicitMods" }
}}
])
这一个会返回“这两个”文件,但只那些具有匹配数组项:
/* 1 */
{
"_id" : ObjectId("5993a35be38f41729f1d6501"),
"name" : "string",
"explicitMods" : [
"12 to 18 to Blah"
]
}
/* 2 */
{
"_id" : ObjectId("5993a35be38f41729f1d6502"),
"name" : "string",
"explicitMods" : [
"12 to 18 to Blah"
]
}
当然可以在该主题应用一个“变化”和“测试长度”对过滤条件的阵列,以便决定哪些文件返回:
db.myCollection.aggregate([
{ "$match": { "explicitMods": /\d+ to \d+/ } },
{ "$addFields": { "origSize": { "$size": "$explicitMods" } } },
{ "$unwind": "$explicitMods" },
{ "$match": { "explicitMods": /\d+ to \d+/ } },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"origSize": { "$first": "$origSize" },
"explicitMods": { "$push": "$explicitMods" },
}},
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$size": "$explicitMods" },
"$origSize"
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
不过,虽然它使用“本地运营商”,这样的操作成本一般为$unwind
使得它的效用值得怀疑,因此可能需要花费很多的时间做同样的事情与$where
原来的选项和资源来生成结果比原始查询。
您是否可以更新您的问题以提供查询返回的示例文档,但您不希望包含该文档? – JohnnyHK
您的查询似乎有效。那么你是否试图在那个文档中过滤'explicitMods'? – Mikey
如果你不想在你的“12到18”之前或之后有任何其他字符 - 换句话说,你可能需要在开始时用'^'或者在表达式结尾的'$'来锚定你的正则表达式 - 换句话说,一个表达式,比如'/^\ d +到\ d + $ /'。这可能有帮助吗? –