【问题标题】:How to query documents in mongodb (pymongo) where all keywords exist in a field?如何在一个字段中存在所有关键字的mongodb(pymongo)中查询文档?
【发布时间】:2016-07-15 02:07:05
【问题描述】:

我有一个关键字列表:

keywords = ['word1', 'word2', 'word3']

现在我只查询 1 个这样的关键字:

collection.find({'documenttextfield': {'$regex': ' '+keyword+' '}})

我绝不是正则表达式的专家,所以我在关键字旁边用空格做雷鬼音乐以找到完全匹配。

但我现在想要的是,拥有 keywords 列表,查询文档并从 documenttextfield 的列表中找到具有每个关键字的文档。

我对如何做到这一点有一些想法,但它们都太复杂了,我觉得我错过了一些东西......

【问题讨论】:

  • 如果您不知道关键字出现的顺序,单个正则表达式将无济于事。您是否考虑过使用text index

标签: python regex mongodb pymongo


【解决方案1】:

考虑使用text index$text search。这可能是比使用正则表达式更好的解决方案。但是,文本搜索会根据评分算法返回文档,因此您可能会得到一些没有您要查找的所有关键字的结果。

如果您不能或不想向该字段添加文本索引,则使用单个正则表达式会非常痛苦,因为您不知道这些单词出现的顺序。我并不是说它是不可能写的,但是即使对于正则表达式标准,你最终也会令人憎恶。通过使用$and 运算符,多次使用正则表达式运算符会容易得多。

此外,当单词位于字符串的开头或结尾或后跟句点或逗号时,使用空格作为分隔符将失败。请改用词边界标记 (\b)。

collection.find(
    { $and : [
              {'documenttextfield': {'$regex': '\b' +keyword1+'\b'}},
              {'documenttextfield': {'$regex': '\b' +keyword2+'\b'}},
              {'documenttextfield': {'$regex': '\b' +keyword3+'\b'}},
         ]
    });

请记住,这是一个非常慢的查询,因为它将在集合的每个文档上运行这三个正则表达式。当这是一个性能关键的查询时,请认真考虑文本索引是否真的不行。如果做不到这一点,最后一根稻草就是从documenttextfield 字段中提取某人可以搜索的任何关键字(可能是其中的每个唯一单词)到一个新的数组字段documenttextfield_keywords 中,然后在该字段上创建一个普通索引字段,然后使用 $all operator 搜索该字段(在这种情况下不需要正则表达式)。

【讨论】:

  • 谢谢!我将尝试将每个文本字段的关键字组合起来并存储在同一个文档中!这实际上是一个非常整洁的好方法。我有办法做到这一点,我认为这肯定比 3 个正则表达式更好!
  • @GeekSince1982 使用$all 远没有{ "documenttextfield": { "$all": [re.compile('\b'+keyword+'\b',re.IGNORECASE) for keyword in keywords] } } 那么迟钝。但除非你需要像"and""or" 这样的“停用词”,否则$text 可能更有效。请注意,它确实需要显着更大的索引才能实现该效率,并且通常适合文档中“较大”的文本字段而不是较小的文本字段。
  • @GeekSince1982 这里的“其他”遗漏是“文本搜索”不会返回与术语列表匹配的文档。 all 匹配的文档将是“排名靠前”的结果,但由于文本搜索条件为“OR”条件,将返回包含的其他术语。没有办法专门写“AND”。另外我上面的主要观点是,答案错误地假定$all 需要 一个数组才能起作用。它不是,实际上当然是一个需要匹配属性的“参数列表”,而不是相反。人们经常犯这个错误。
  • 我尝试使用 $text 搜索并在 {score:{ $meta: "textScore"}} 上进行排序。它工作正常,但textScore 不是很可靠,或者我可能不完全理解评分机制。基本上我看到,如果一个关键字被多次提及或所有关键字都被找到,结果会得到高分。虽然我需要确定所有关键字的结果。
猜你喜欢
  • 1970-01-01
  • 2020-05-26
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
相关资源
最近更新 更多