如何在MongoDB中搜索逗号分隔的数据

4
我有一个电影数据库,其中包含不同的字段。Genre字段包含逗号分隔的字符串,例如:
{genre: 'Action, Adventure, Sci-Fi'}

我知道我可以使用正则表达式来查找匹配项。我也尝试过:
{'genre': {'$in': genre}}

问题在于运行时间。返回查询结果需要很长时间。数据库大约有30万个文档,我已经对“类型”字段进行了普通索引。
2个回答

3

建议使用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"
    ]
}

此外,贪婪匹配符“*”非常耗费资源且不必要。 - user3561036

0

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

如果你想在原地使用字符串中的“逗号分隔”数据来完成这个任务,你需要这样做:

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

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

但并不是非常高效。

或者通过 JavaScript 评估来实现,如 $where

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方法,以下是结果: [数据库中的记录数: 289705] [添加新集合以只保留流派: 25.2529330254秒] [map/reduce操作: 27.657秒] [创建索引: 3秒] [每个查询: 0.311秒] - Ahmad Mousavi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接