【问题标题】:MongoDB text search filter by multiple fieldsMongoDB 文本搜索过滤器按多个字段
【发布时间】:2015-03-15 07:08:05
【问题描述】:

我有以下文档结构。

{
   content: 'cat dog bird',
   uid: <another_unique_id>
   cid: <another_unique_id>
}

我正在尝试搜索此集合并希望按uid 和/或cid 过滤结果。我想运行的一些查询:

1) db.mycollection.find({uid: '1', cid: '2', $text: {$search: 'cat'}});         
2) db.mycollection.find({cid: '2', $text: {$search: 'cat'}});
3) db.mycollection.find({uid: '1', $text: {$search: 'cat'}});
4) db.mycollection.find({$text: {$search: 'cat'}});
//etc...

我试图创建一个像这样的复合索引

db.mycollection.ensureIndex({uid: 1, cid: 1, content: 'text'});

但它仅适用于查询 #1,如果我不提供其中一个字段,我会收到以下错误。

planner returned error: failed to use text index to satisfy $text query 
(if text index is compound, are equality predicates given for all prefix fields?)

我尝试过的其他事情:

  1. uid/cid 上创建非复合索引 = 会导致大量文档被扫描

  2. uid cid 索引移到文本索引之后,即

    db.mycollection.ensureIndex({content: 'text', uid: 1, cid: 1});

    与 #1 相同,未使用 uid 和 cid 索引。

关于我正在尝试的信息: http://docs.mongodb.org/manual/tutorial/limit-number-of-items-scanned-for-text-search/

我是否遗漏了什么,或者这对于使用索引的 MongoDB 来说是不可能的?

【问题讨论】:

  • 不确定这是否可行。阅读:docs.mongodb.org/manual/tutorial/…。如果查询的字段只是索引的一部分,则查询不能使用索引。设计有关您实际使用情况的索引。可能检查索引交集。
  • 我正在查看 stackoverflow.com/questions/24257390/… 即在 content uidcid 的 3 个字段上创建文本索引,但我还没有找到一种方法来使用它进行查询还没有。
  • 索引的声明顺序很重要。在您的第一个声明中,仅当您的查询使用 uid 或 (uid and cid) 或 (uid and cid and text) 时才会使用索引。

标签: mongodb mongodb-query


【解决方案1】:

completely documented 不仅是预期的行为,而且我还发现您的断言是错误的。在可以满足您指定条件的标准样品上,结果将如图所示。但首先是文档参考:

  • 如果复合文本索引包含文本索引键之前的键,则要执行 $text 搜索,查询谓词必须包含前面键的相等匹配条件。

然后是有效查询的解释输出:

{
    "queryPlanner" : {
       "plannerVersion" : 1,
       "namespace" : "test.mycollection",
       "indexFilterSet" : false,
       "parsedQuery" : {
           "$and" : [
               {
                   "cid" : {
                       "$eq" : 2
                   }
               },
               {
                   "uid" : {
                       "$eq" : 1
                   }
               },
               {
                   "$text" : {
                       "$search" : "cat",
                       "$language" : ""
                   }
               }
          ]
      },
      "winningPlan" : {
          "stage" : "TEXT",
          "indexPrefix" : {
               "uid" : 1,
               "cid" : 2
          },
          "indexName" : "uid_1_cid_1_content_text",
          "parsedTextQuery" : {

          }
      },
      "rejectedPlans" : [ ]
  },
  "serverInfo" : {
      "host" : "trashbox",
       "port" : 27017,
       "version" : "3.0.0",
       "gitVersion" : "a841fd6394365954886924a35076691b4d149168"
  },
  "ok" : 1
}

因此,如果您要发出与您实际创建的“复合键”具有不同模式并且符合明确指定的规则的查询,那么您可能还应该注意要点:

  • 一个集合最多可以有一个文本索引。

因此,在“任何形式”的复合或其他形式中,如果您正在寻找不止一个 MongoDB 文本索引的定义,那么您就不能这样做。这同样适用于“地理空间”索引,以及在$or 表达式或.sort() 之外的一般考虑,查询引擎一次只能选择一个索引。

现代版本应报告非常具体的行以及错误:

(如果文本索引是复合索引,是否为所有前缀字段提供相等谓词?)

所以“所有”字段都是必需的,并且它们“必须”完全匹配,而不使用不等式运算符。

如果您不打算“始终”使用其他字段作为具有“完全匹配”条件的查询的一部分,那么您将无法与文本搜索一起形成复合索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2014-04-30
    • 2016-11-23
    • 1970-01-01
    相关资源
    最近更新 更多