【问题标题】:How to search comma separated data in mongodb如何在mongodb中搜索逗号分隔的数据
【发布时间】:2015-09-05 14:23:59
【问题描述】:

我有不同领域的电影数据库。 Genre 字段包含一个逗号分隔的字符串,例如:

{genre: 'Action, Adventure, Sci-Fi'}

我知道我可以使用正则表达式来查找匹配项。我也试过了:

{'genre': {'$in': genre}}

问题是运行时间。返回查询结果需要很长时间。数据库有大约 300K 文档,我已经对“流派”字段进行了正常索引。

【问题讨论】:

    标签: regex performance mongodb mongodb-query


    【解决方案1】:

    会说使用 Map-Reduce 创建一个单独的集合,将 genre 存储为一个数组,其值来自拆分的逗号分隔字符串,然后您可以运行 Map-Reduce 作业并管理对输出集合的查询。

    例如,我为foo 集合创建了一些示例文档:

    db.foo.insert([
        {genre: 'Action, Adventure, Sci-Fi'},
        {genre: 'Thriller, Romantic'},
        {genre: 'Comedy, Action'}
    ])
    

    然后,以下 map/reduce 操作将生成您可以应用高性能查询的集合:

    map = function() {
        var array = this.genre.split(/\s*,\s*/);
        emit(this._id, array);
    }
    
    reduce = function(key, values) {
        return values;
    }
    
    result = db.runCommand({
        "mapreduce" : "foo", 
        "map" : map,
        "reduce" : reduce,
        "out" : "foo_result"
    });
    

    查询很简单,利用value 字段上的多键索引查询:

    db.foo_result.createIndex({"value": 1});
    
    var genre = ['Action', 'Adventure'];
    db.foo_result.find({'value': {'$in': genre}})
    

    输出

    /* 0 */
    {
        "_id" : ObjectId("55842af93cab061ff5c618ce"),
        "value" : [ 
            "Action", 
            "Adventure", 
            "Sci-Fi"
        ]
    }
    
    /* 1 */
    {
        "_id" : ObjectId("55842af93cab061ff5c618d0"),
        "value" : [ 
            "Comedy", 
            "Action"
        ]
    }
    

    【讨论】:

    • 另外,贪婪匹配“*”是非常昂贵且不必要的。
    【解决方案2】:

    嗯,你不能真正有效地做到这一点,所以我很高兴你在你的问题上使用了“性能”标签。

    如果您想使用字符串中的“逗号分隔”数据执行此操作,您需要执行以下操作:

    如果合适的话,一般可以使用正则表达式:

    db.collection.find({ "genre": { "$regex": "Sci-Fi" } })
    

    但效率不高。

    或通过 $where 进行 JavaScript 评估:

    db.collection.find(function() {
         return ( 
             this.genre.split(",")
                 .map(function(el) { 
                     return el.replace(/^\s+/,"") 
                 })
                 .indexOf("Sci-Fi") != -1;
        )
    })
    

    效率不高,可能与上述相同。

    或者更好的是,可以使用索引,独立于数组并使用基本查询:

    {
        "genre": [ "Action", "Adventure", "Sci-Fi" ] 
    }
    

    带索引:

    db.collection.ensureIndex({ "genre": 1 })
    

    然后查询:

    db.collection.find({ "genre": "Sci-Fi" })
    

    当你这样做时,它就是那么简单。而且真的高效。

    你做出选择。

    【讨论】:

    • 我实现了 Map-Reduce 方法。结果如下:[db 中的记录:289705] [添加新集合以仅具有流派:25.2529330254 秒] [map/reduce 操作:27.657 秒] [创建索引:3 秒] [每个查询:0.311 秒]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多