MongoDB文本搜索按多个字段过滤

时间:2015-03-15 07:08:05

标签: mongodb mongodb-query

我有以下文档结构。

{
   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索引相同。

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

    我是否遗漏了某些东西,或者MongoDB使用索引是不可能的?

1 个答案:

答案 0 :(得分:4)

不仅是预期的行为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
}

因此,如果您想发出具有不同模式的查询,请使用&#34;复合键&#34;你实际上已经创建并且符合明确指定的规则,那么你可能也应该注意主要观点:

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

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

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

  

(如果文本索引是复合的,是否为所有前缀字段给出了等式谓词?)

所以&#34;所有&#34;这些领域是必需的,他们必须是&#34;完全匹配而不使用不等式运算符。

如果你不打算&#34;总是&#34;使用其他字段作为查询的一部分,使用&#34;完全匹配&#34;条件然后你不能与文本搜索一起形成复合索引。