gpt4 book ai didi

javascript - 为什么这个 RegExp 查询返回所有结果?

转载 作者:可可西里 更新时间:2023-11-01 09:48:14 25 4
gpt4 key购买 nike

我有一个 MongoDB 3.2 服务器。我的收藏包含如下文档:

{
"name": "string",
"explicitMods": [
"+48 to Blah",
"-13% to Blah",
"12 to 18 to Blah"
]
}

如果我这样写:

myCollection.find({ "explicitMods": /bad string/ })

如预期的那样,我得到零结果。

但是如果我这样写:

myCollection.find({ "explicitMods": /\d+ to \d+/ })

我得到了集合中的所有文档。这是出乎意料的,因为我实际上想要包含 12 到 18 等子字符串的文档。如果我将正则表达式更改为 /\d+ 到\d+z/ 它正确匹配任何内容。

最佳答案

您发出的查询“正确地” 返回与您要求的条件实际匹配的文档。也就是说,您正在测试的属性中的“至少一个”数组元素实际上与查询中的条件匹配。

由此我们可以推测出两种可能的结果:

  1. 您的目的是仅返回所有 数组条目满足条件的文档。

  2. 您的目的是“过滤”“文档中的数组”中的条目,仅返回满足条件的结果。

其中有不同的方法。首先,实际上 MongoDB 没有这样的查询运算符,它要求“所有”数组元素必须满足“常规查询”的给定条件。因此,您需要以不同的形式应用逻辑。

其中一个选项是使用 $where 的 JavaScript 求值。以检查数组内容的方式。这里可以申请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"
]
}

在替代情况下使用 $where ,MongoDB 的聚合框架允许使用“ native 编码运算符”的表达式,这通常比 JavaScript 解释表达式应用得更快。然而实际上并没有与SERVER-11947 等价的“逻辑运算符”(见$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"
}
}}
])

但是虽然它与 $where 的原始选项做同样的事情使用“ native 运算符”,此类操作的一般成本为 $unwind使它的实用性受到质疑,因此可能比原始查询花费更多的时间和资源来生成结果。

关于javascript - 为什么这个 RegExp 查询返回所有结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45703608/

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