【问题标题】:MongoDB query to find documents with variationsMongoDB查询以查找具有变化的文档
【发布时间】:2019-05-24 22:37:50
【问题描述】:
示例 MongoDB 文档:
{
name: "something"
product: "ABC-123"
}
问题是产品可能并不总是遵循相同的命名约定。可以是以下任何一种
"ABC-123"
"ABC123"
"ABC 123"
因此,如果我搜索“ABC-123”,我想要任何类似匹配的文档,而不管命名约定的变化。
【问题讨论】:
标签:
node.js
regex
mongodb
mongodb-query
regex-group
【解决方案1】:
编辑:您可以使用表达式^ABC(?:.*?)\\d+$ 在查询中简单地使用$regex,如下所示:
示例 MongoDB 文档:
db={
"products": [
{
"name": "product A",
"product": "ABC-123"
},
{
"name": "product B",
"product": "ABC123"
},
{
"name": "product C",
"product": "ABC-123"
}
]
}
查询:
db.products.find({
"product": {
"$regex": "^ABC(?:.*?)\\d+$"
}
})
演示:https://mongoplayground.net/p/WdqTg7LCZIk
我们也许可以找到这个问题的表达式。也许,让我们从类似于以下的表达式开始:
product:\s+"(.+?)"
这里,我们使用product:\s+"作为左边界,然后我们收集任何字符,然后我们从右边界使用"。
const regex = /product:\s+"(.+?)"/gm;
const str = `{
name: "something"
product: "ABC-123"
}`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
或者我们可以将它扩展到我们喜欢捕获而不是捕获的内容:
(?:product:\s+")(.+?)(?:")
【解决方案2】:
如果您的变化就是这样,而这就是您的 3 种可能性,那么 Emma 的答案正是您所需要的。如果正则表达式失控并且您最终拥有许多不同的产品变体,您还有另一个选择是$textsearch/index AND regEx。
例如:
db.getCollection('COLNAME').find({
$or: [
{
$text: {$search: 'abc'} // By default it is case insensitive
},
{
product: {"$regex": "YOUR_REGEX_HERE"}
}
]
})
这也是高效的,因为您将在 product 上拥有一个文本索引以及一个常规索引。这也将处理XXX-ABC 和您可能不知道/拥有的任何其他变体之类的情况。所以要考虑一下。