如何在mongodb中有效过滤

时间:2015-08-13 08:33:26

标签: mongodb mongodb-query

我有这样的示例文档,

{year:2015, brand:"mq", model:"ma"},
{year:2015, brand:"mq", model:"mb"},
{year:2015, brand:"mq", model:"mc"}

使用此

查询文档
{year:2015, brand:"mq", model:"ma"}

在这个查询之后我只能得到一个你想象的结果,但我想得到的结果就是这个,

{year:2015, brand:"mq", model:"ma"}, -> first result that matches the most
{year:2015, brand:"mq", model:"mb"}, -> second
{year:2015, brand:"mq", model:"mc"}  -> third

我已经搜索了很多,但我找不到任何相关内容,我有一个脚本,我写的也是为了得到那些结果,但是在索引使用方面效率不高,我怎么能管理这个问题呢我的?谢谢

1 个答案:

答案 0 :(得分:2)

基本查询方面,text search和索引最有效。

因此,如果你创建一个这样的文本索引:

 db.collection.createIndex({ "year": "text", "brand": "text", "model": "text" })

然后发出如下查询:

db.junk.find({ "$text": { "$search": "2015 mq ma" } })

它将返回如下结果:

{
        "_id" : ObjectId("55cc56d5ca1af2140f5e283c"),
        "year" : 2015,
        "brand" : "mq",
        "model" : "ma",
        "score" : 2.2
}
{
        "_id" : ObjectId("55cc56d5ca1af2140f5e283d"),
        "year" : 2015,
        "brand" : "mq",
        "model" : "mb",
        "score" : 1.1
}
{
        "_id" : ObjectId("55cc56d5ca1af2140f5e283e"),
        "year" : 2015,
        "brand" : "mq",
        "model" : "mc",
        "score" : 1.1
}

已根据搜索中与索引中指定的字段匹配的术语数进行排名。请注意,数字类型无关紧要,并被视为" text"通过搜索本身。

或者,如果您担心文本索引使用的额外空间,那么您始终可以使用.aggregate()方法手动处理此问题。在计算"分数"时会有一些开销,但它相当小:

db.collection.aggregate([
  { "$match": {
    "$or": [
      { "year": 2015 },
      { "brand": "mq" },
      { "model": "ma" }
    ]
  }},
  { "$project": {
    "year": 1, 
    "brand": 1,
    "model": 1,
    "score": {
      "$add": [
        { "$cond": [ { "$eq": [ "$year", 2015 ] }, 1, 0] },
        { "$cond": [ { "$eq": [ "$brand", "mq" ] }, 1, 0 ] },
        { "$cond": [ { "$eq": [ "$model", "ma" ] }, 1, 0 ] }
      ]
    }
  }},
  { "$sort": { "score": -1 } }
])

产生类似的结果:

{
        "_id" : ObjectId("55cc56d5ca1af2140f5e283c"),
        "year" : 2015,
        "brand" : "mq",
        "model" : "ma",
        "score" : 3
}
{
        "_id" : ObjectId("55cc56d5ca1af2140f5e283d"),
        "year" : 2015,
        "brand" : "mq",
        "model" : "mb",
        "score" : 2
}
{
        "_id" : ObjectId("55cc56d5ca1af2140f5e283e"),
        "year" : 2015,
        "brand" : "mq",
        "model" : "mc",
        "score" : 2
}

但是你想要遵循的基本方法是增加一个重量"到匹配的条款,然后相应地对结果进行排序。

至于选择哪一项,一切都取决于你想要做什么。文本索引将自动分配权重,该权重可与排序中的$meta属性一起使用,如图所示。你甚至可以设置"体重"在创建索引时单独对每个字段进行处理,因此如果需要,某些字段将比其他字段更多地影响结果。

同样的道理,在聚合过程中自己分配这个,可以提供更多控制,如果需要,可以为不同的查询分配不同的权重,并且你也可以构成更复杂的规则。

使用"文字"索引,这是相当的静态"因为这些规则是在索引本身上定义的。此外,文本索引需要比普通索引多一点的空间,特别是如果在正常索引就足够时有其他查询。

选择"哪个最好"实际上是关于您的应用程序对数据执行的操作以及您经常执行的查询类型。一如既往,"基准"并在所有条件下观察应用程序和服务器行为。这通常会为您提供最适合您的选择的最佳资源。