Mongodb-多文本索引:索引键模式太大错误代码67

Mongodb-多文本索引:索引键模式太大错误代码67,mongodb,indexing,mongodb-query,nosql,Mongodb,Indexing,Mongodb Query,Nosql,我有以下Mongodb数据库结构: { "_id" : "519817e508a16b447c00020e", "keyword" : "Just an example query", "rankings" : { results: { "1" : { "domain" : "example1.com", "href" : "http://www.example1.com/"},

我有以下Mongodb数据库结构:

{ 
    "_id" : "519817e508a16b447c00020e", 
    "keyword" : "Just an example query", 
    "rankings" : 
    {
        results:
        {
            "1" : { "domain" : "example1.com", "href" : "http://www.example1.com/"},
            "2" : { "domain" : "example2.com", "href" : "http://www.example2.com/"},
            "3" : { "domain" : "example3.com", "href" : "http://www.example3.com/"},
            "4" : { "domain" : "example4.com", "href" : "http://www.example4.com/"},
            "5" : { "domain" : "example5.com", "href" : "http://www.example5.com/"},
            ...
            ...
            "99" : { "domain" : "example99.com", "href" : "http://www.example99.com/"}
            "100" : {"domain" : "example100.com", "href" : "http://www.example100.com/"}
        }, 
        "plus":"many", 
        "other":"not", 
        "interesting" : "stuff", 
        "for": "this question"
    }
}
,我询问如何为文本编制索引,以便使用以下示例搜索关键字和域:

db.ranking.find({ $text: { $search: "\"example9.com\" \"Just an example query\""}})  
> db.ranking.find({"keyword":"how are you doing", "rank_date" : "2014-08-27”)
John Petrone给出的令人敬畏的答案是:

db.ranking.ensureIndex(
{
    "keyword": "text",
    "rankings.results.1.domain" : "text",
    "rankings.results.2.domain" : "text",
    ...
    ...
    "rankings.results.99.domain" : "text",
    "rankings.results.100.domain" : "text"
}
然而,如果当我有10个结果时效果很好,那么当我尝试索引100个结果时,我遇到了一个索引键模式太大的错误,代码67来自MongoShell

所以最大的问题是:

我该如何解决索引键模式太大的错误

编辑:18/08/2014 文件结构得到澄清

{ 
    "_id" : "519817e508a16b447c00020e", #From Mongodb
    "keyword" : "Just an example query", 
    "date" : "2014-03-28"
    "rankings" :
    {
            "1" : { "domain" : "example1.com", "href" : "http://www.example1.com/", "plus" : "stuff1"},
            ...
            "100" : {"domain" : "example100.com", "href" : "http://www.example100.com/"plus" : "stuff100"}"}
    }, 
    "plus":"many", 
    "other":"not", 
    "interesting" : "stuff", 
    "for": "this question"
}

您建议的结构存在的问题:

{
 keyword" : "Just an example query", 
 "rankings" :
    [{"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
     ...{ "rank" : 99, "domain" : "example99.com", "href" : "example99.com“}
 ]}
}
那是不是尽管你现在能做到

db.ranking.ensureIndex({"rankings.href":"text", "rankings.domain":"text"}) 
然后运行如下查询:

db.ranking.find({$text:{$search:"example1"}});
现在将返回匹配数组元素的整个数组文档

您可能需要考虑引用,以便每个排名结果是一个单独的文档,引用关键字和其他元数据,以避免重复大量信息。 因此,您有一个关键字/元数据文档,如:

{_id:1, "keyword":"example query", "querydate": date, "other stuff":"other meta data"},
{_id:2, "keyword":"example query 2", "querydate": date, "other stuff":"other meta data 2"}
{keyword_id:1, {"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
... keyword_id:1, {"rank" : 99, "domain" : "example99.com", "href" : "example99.com"},
 keyword_id:2, {"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
 ...keyword_id:2, {"rank" : 99, "domain" : "example99.com", "href" : "example99.com"}}
然后是一个结果文档,如:

{_id:1, "keyword":"example query", "querydate": date, "other stuff":"other meta data"},
{_id:2, "keyword":"example query 2", "querydate": date, "other stuff":"other meta data 2"}
{keyword_id:1, {"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
... keyword_id:1, {"rank" : 99, "domain" : "example99.com", "href" : "example99.com"},
 keyword_id:2, {"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
 ...keyword_id:2, {"rank" : 99, "domain" : "example99.com", "href" : "example99.com"}}
其中关键字id链接回引用关键字/元数据表-显然,在实践中,_id看起来像_id:519817e508a16b447c00020e,但这只是为了可读性。现在,您可以根据查询类型一起或分别对关键字_id、domain和href进行索引,并且不会得到索引键模式太大的错误,您只会得到一个匹配的文档,而不会返回整个数组

我不完全清楚您在哪里需要模糊/正则表达式风格的搜索,以及您是要搜索元数据还是只搜索href和domain,但我认为这种结构应该是一种更干净的方式来开始考虑索引,而不必像以前那样过多地使用索引。它还允许您根据您的查询模式,将普通索引上的查找与文本索引相结合

在考虑文档结构时,您可能会发现这个答案很有用。

因此,这就是我的解决方案: 我决定通过一个过于简单的修改继续使用嵌入文档:将包含实际秩的字典键替换为包含秩的数组,仅此而已:

{ 
  "_id" : "519817e508a16b447c00020e", #From Mongodb
  "keyword" : "Just an example query", 
  "date" : "2014-03-28"
  "rankings" :
  [
    { 
      "domain" : "example1.com", "href" : "http://www.example1.com/", "plus" : "stuff1", "rank" : 1
    },
    ...
    {
      "domain" : "example100.com", "href" : "http://www.example100.com/"plus" : "stuff100", "rank" : 100
    }
  ]
  "plus":"many", 
  "more":"uninteresting", 
  "stuff" : "for", 
  "this": "question"
}
然后,我可以选择整个文档,例如:

db.ranking.find({ $text: { $search: "\"example9.com\" \"Just an example query\""}})  
> db.ranking.find({"keyword":"how are you doing", "rank_date" : "2014-08-27”)
或者使用投影的单一结果,这非常棒,是Mongodb 2.6:-D中的一个新特性

> db.collection.find({ "rank_date" : "2014-04-09", "rankings.href": "http://www.example100.com/" }, { "rankings.$": 1 })

  [
    { 
      "domain" : "example100.com", "href" : "http://www.example100.com/", "plus" : "stuff100", "rank" : 100
    },
  ]
甚至可以直接获得一个url排名:

> db.collection.find({"rank_date" : "2014-04-09", "rankings.href": "http://www.example5.com/"}, { "rankings.$": 1 })[0]['rankings'][0]['rank']
5
最后,我还基于url创建了一个索引:

> db.collection.ensureIndex( {"rankings.href" : "text"} )
通过索引,我可以搜索单个url、部分url、子域或整个域,这非常棒:

> db.collection.find({ $text: { $search: "example5.com"}})

真的就是这样!非常感谢大家的帮助,尤其是@JohnBarça:-D

当我看到最初的问题时,我突然想到这会很快成为一个问题。没有办法改变结构吗?这是从外部API接收的json。但是,如果我更改了结构,您会推荐什么以及如何设置索引?您想在查询中同时引用域和href吗?同等重量?假设_id来自每一组搜索,因此您可以有多个文档,每个文档都有一个不同的_id和一个结果数组,其中包含href和domain?在给出答案之前,我只想澄清一下。用例是什么?我觉得一个不同的数据模型是最好的方法。和你的例子中的完全匹配?或关键字/文本搜索匹配?在域和href字段上进行文本搜索,还是只搜索关键字字段?谢谢,这是一个非常有趣的答案,很遗憾我还不能投票。你发表的参考文章很棒,实际上我没有考虑分裂。但是为什么不为结果文档提供一个更平坦的结构,比如:{关键字_id:1,排名:1,域:example1-1.com,href:example1-1.com}。。。{关键字id:1,排名:99,域:example1-99.com,href:example1-99.com},{关键字id:2,排名:1,域:example2-1.com,href:example2-1.com}。。。{keyword_id:1,rank:99,domain:example2-99.com,href:example2-99.com}这也是一篇非常有趣的文章是的,你可以选择这样一个完全扁平的结构。我在想,您可能希望在对api的每一组请求周围单独保存元数据,但是平面结构肯定会工作,并且易于索引和查询。非常好的文章。关于查询数组的评论或多或少地暗示了我的意思