Запрос MongoDB для поиска документов с вариантами - PullRequest
1 голос
/ 25 мая 2019

Пример документа MongoDB:

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

Проблема в том, что продукт может не всегда следовать одному и тому же соглашению об именах. Это может быть любой из следующих

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

Поэтому, если я ищу «ABC-123», я хочу, чтобы любой документ соответствовал одинаково, независимо от варианта соглашения об именах.

Ответы [ 2 ]

2 голосов
/ 25 мая 2019

Редактировать: Вы можете просто использовать $ regex в своем запросе, используя выражение ^ABC(?:.*?)\\d+$, например:

Пример документа 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+")(.+?)(?:")

DEMO

enter image description here

1 голос
/ 25 мая 2019

Если ваш вариант - это именно то, и это ваши 3 возможности, тогда ответ от Эмма - это то, что вам нужно.Другой вариант, который у вас есть, если регулярное выражение выходит из-под контроля, и вы в конечном итоге получаете много различных вариантов продукта, - это $ text search / 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 и любых других вариантах, которые вы можете не знать / не иметь.Так что подумайте.

...