MongoDB查询以查找具有变体的文档

时间:2019-05-24 22:37:50

标签: node.js regex mongodb mongodb-query regex-group

MongoDB文档示例:

{
  name: "something"
  product: "ABC-123"
}

问题是产品可能并不总是遵循相同的命名约定。可能是以下任何一个

"ABC-123"
"ABC123"
"ABC 123"

因此,如果我搜索“ ABC-123”,则无论命名约定如何变化,我都希望任何文档都具有相似的匹配性。

2 个答案:

答案 0 :(得分:2)

编辑:您只需在查询中使用表达式^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+"(.+?)"

Demo

在这里,我们使用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+")(.+?)(?:")

DEMO

enter image description here

答案 1 :(得分:1)

如果仅此而已,那是您的3种可能性,那么 Emma 的答案正是您所需要的。如果正则表达式失控并且最终导致很多不同的产品款式,您可以选择的另一种选择是$text搜索/索引和regEx。

例如:

db.getCollection('COLNAME').find({
  $or: [
    {
      $text: {$search: 'abc'}  // By default it is case insensitive
    },
    {
      product: {"$regex": "YOUR_REGEX_HERE"}
    }
  ]
})

由于您将在product上有一个文本索引以及一个常规索引,因此这也将很有效。这也可以处理诸如XXX-ABC之类的情况以及您可能不知道/不知道的其他任何变体。所以要考虑一下。