mongo db-搜索字符串的有效方法

时间:2019-03-11 14:17:13

标签: mongodb mongoose

我正在寻找要分解为前缀,数字和字母的字符串,我目前需要搜索5500万行,并且行看起来像这样(我还保存了整个字符串的简化版本):

{ "prefix" : "AA", "numbers" : "02", "letters" : "AFO", "code" : "AA02AFO" "price" : "699" }

最有效的搜索方式是,如果我想进行组合搜索,该搜索将完全符合上述条件,但还会返回类似以下内容的匹配结果:

AA*AFO
A*AFO
*A02AFO
**02AFO

以此类推,如果存在该匹配项,我想返回一个完全匹配项,并且还希望返回与搜索记录相似的任何记录。

我目前在除价格之外的所有其他字段上都有一个索引,并在辅助代码上有一个索引。如果一个字符串匹配多个正则表达式,还有没有一种方法可以确保查询返回不同的结果?

3 个答案:

答案 0 :(得分:2)

首先,将查询构造为针对字符串的正则表达式将是效率最低的查询方式之一。相反,您应该按实际字段进行查询:

{
$or: [
  {prefix: "AA", numbers: "02", "letters": "AFO"}, -- full match
  {prefix: {$exists: true}, numbers: "02", "letters: "AFO" } -- varying prefix,
   ...etc
]}

按实际字段进行查询将使Mongo有效地使用索引。像/^..02AFO/这样的正则表达式将需要检查索引中的每个记录是否匹配。

  

我目前在除价格之外的所有其他字段上都有一个索引,并在辅助代码上有一个索引。如果一个字符串匹配多个正则表达式,还有没有一种方法可以确保查询返回不同的结果?

如果您确实想与正则表达式匹配,则可以使用$in组合多个正则表达式并仅返回唯一的匹配文档:{code: {$in: [/foo/, /bar/] }

您还可以使用$or{$or: [{code: /foo/}, {code: /bar/}], otherCriterion: "yay"}

答案 1 :(得分:1)

您可以使用$regex查询运算符来测试每个正则表达式。您可以通过记录的code对结果进行交叉引用,以查看它是否在多个结果中:

const regexes = [
  /AA*AFO/,
   ...
];

const results = {};

regexes.forEach(async (regex) => {
  results[regex] = await db.collection.find(
    {
      code: {
        $regex: regex
       }
    });
});

答案 2 :(得分:1)

我将支持Willis的回答,并建议您对字符串的每个组成部分进行精确匹配。但是,如果这还不够灵活(例如,您还希望能够在每个组件中内部进行部分匹配),我建议您设置一个镜像的ElasticSearch引擎,尤其是考虑到您有多少条记录时。 MongoDB并非真正旨在进行高效的自由格式文本搜索。

我个人的经验是,即使对连接的字符串字段建立索引,大约有1000万条记录,即使有足够的RAM来容纳(相当大的)索引,执行自由形式搜索每个查询也要花费30秒以上的时间。当我试图在文本字段上进行实时自动完成时,这是行不通的:-)

ElasticSearch有几种解决方案,可以将数据从mongodb自动复制到其自己的数据库中,因此,我发现在完成所有设置后,它运行起来非常顺利。我使用monstache(https://github.com/rwynn/monstache),但也有其他。我意识到这并不是您所要的,但我经历了一个痛苦的过程,即尝试优化mongodb以进行自由形式的文本搜索,但是这种搜索并没有永远结束,最终还是放弃了。如果这将是一种常见的查询,并且您需要良好的性能,我强烈建议您研究针对它进行了优化的类似ElasticSearch的内容。