2012-08-10 71 views
2

我有以下结构的文件:应用条件的多个文件对同一领域的MongoDB

user {id: 123, tag:"tag1"} 
user {id: 123, tag:"tag2"} 
user {id: 123, tag:"tag3"} 
user {id: 456, tag:"tag1"} 

鉴于用户ID,我想找到如果该用户已经记录了所有3个标签(操作数) 。 如果用户对“标签1”和“与Tag2”与“标签3”的记录,然后返回true

SQL相当于将是这样的:

SELECT * FROM users WHERE 
    EXISTS (SELECT * FROM tags WHERE user_id = users.id AND name ='tag1') AND 
    EXISTS (SELECT * FROM tags WHERE user_id = users.id AND name ='tag2') AND 
    user_id=123 

我怎样才能表达MongoDB的东西simular?

+0

做这些查询需要有多快呢?您可以使用聚合框架按ID分组标签,然后匹配所需条件。 – 2012-12-11 06:36:44

回答

4

因为MongoDB没有联接的概念,所以需要通过减少对单个文档的输入来解决这个问题。

如果你改变你的文档结构,以便您存储标签的数组,如下所示:

{id: 123, tag:["tag1","tag2","tag3"]} 
{id: 456, tag:["tag1"]} 

你可以做一个查询如下所示:

db.user.find({$and:[{tag:"tag1"},{tag:"tag2"},{tag:"tag3"}]}) 

如果需要的话,你可以编写一个map-reduce来为userid发出一个标签数组,以便你可以对它进行上面的查询。

编辑 - 包括一个简单的地图,减少

这是一个非常简单的地图,减少获取初始投入的格式是上面给出的find查询有用。

var map = function() {emit(this.id, {tag:[this.tag]});} 
var reduce = function(key, values){ 
    var result_array=[]; 
    values.forEach(function(v1){    
     v1.tag.forEach(function(v2){ 
     result_array.push(v2); 
     }); 
    }); 
return {"tag":result_array};} 

var op = db.user.mapReduce(map, reduce, {out:"mr_results"}) 

然后你就可以在地图上,减少输出集合查询,如下所示:

db.mr_results.find({$and:[{"value.tag":"tag1"},{"value.tag":"tag2"}, {"value.tag":"tag3"}]}) 
+0

我想,问题没有正确回答。地图/减少以及你的方法的例子,会让他更好地理解。 – 2012-08-10 07:23:03

+0

@RaviKhakhkhar用简单的map-reduce更新了答案 – 2012-08-13 01:25:07

+0

谢谢。 upvoted :) – 2012-08-13 06:18:06

相关问题