2015-09-23 14 views
0

我有一个名为Post的模型,女巫包含一个属性数组,其中包含用户标识的属性数组。MongoDB:查询模型并检查文档是否包含对象,然后标记/组结果

现在,我需要查询帖子模型,并标记返回的结果与用户在客户端使用的requestedBySelf true/false - 这可能吗?

我不必在数据库中存储likedBySelf属性,只需修改结果以获得该属性即可。

我发现的一个临时解决方案是做2个查询,一个发现用户x喜欢的帖子,还有那些用户x没有喜欢的帖子,以及en map(设置likesBySelf true/false)和组合2个数组并返回组合数组。但是这给其他查询函数(如限制和跳过)提供了一些限制。

所以现在我的疑问是这样的:

var notLikedByQuery = Post.find({likedBy: {$ne: req.body.user._id}}) 
var likedByQuery = Post.find({likedBy: req.body.user._id}) 

(我使用的是猫鼬LIB)

PS。一个典型的后可以像这样(JSON):

{ 
    "_id": { 
     "$oid": "55fc463c83b2d2501f563544" 
    }, 
    "__t": "Post", 
    "groupId": { 
     "$oid": "55fc463c83b2d2501f563545" 
    }, 
    "inactiveAfter": { 
     "$date": "2015-09-25T17:13:32.426Z" 
    }, 
    "imageUrl": "https://hootappprodstorage.blob.core.windows.net/devphotos/55fc463b83b2d2501f563543.jpeg", 
    "createdBy": { 
     "$oid": "55c49e2d40b3b5b80cbe9a03" 
    }, 
    "inactive": false, 
    "recentComments": [], 
    "likes": 8, 
    "likedBy": [ 
     { 
      "$oid": "558b2ce70553f7e807f636c7" 
     }, 
     { 
      "$oid": "559e8573ed7c830c0a677c36" 
     }, 
     { 
      "$oid": "559e85bced7c830c0a677c43" 
     }, 
     { 
      "$oid": "559e854bed7c830c0a677c32" 
     }, 
     { 
      "$oid": "559e85abed7c830c0a677c40" 
     }, 
     { 
      "$oid": "55911104be2f86e81d0fb573" 
     }, 
     { 
      "$oid": "559e858fed7c830c0a677c3b" 
     }, 
     { 
      "$oid": "559e8586ed7c830c0a677c3a" 
     } 
    ], 
    "location": { 
     "type": "Point", 
     "coordinates": [ 
      10.01941398718396, 
      60.96738099591897 
     ] 
    }, 
    "updatedAt": { 
     "$date": "2015-09-22T08:45:41.480Z" 
    }, 
    "createdAt": { 
     "$date": "2015-09-18T17:13:32.426Z" 
    }, 
    "__v": 8 
} 
+0

你能为你的收藏提供json吗? –

+0

@HarshPatel我现在在问题中包含了一个JSON示例。 – tskippe

回答

0

我发现MongoDB与$ project tequnique的聚合是我最好的选择。所以我写了一个这样的聚合。

说明: 由于我想保留整个文档,但是$项目的目的是修改文档,因此您必须指定要保留的属性。保留所有属性的简单方法是使用“$$ ROOT”。

所以我定义了一个$ project,将我所有的原始属性设置为doc:“$$ ROOT”,然后创建一个新的属性“likedBySelf”,如果指定的USERID在$ likedBy集合中,则标记为true/false 。

我认为这比查询后查询每个单个模型更加干净和简单,以设置一个likedBySelf标志。它可能不会更快,但它更干净。

Model.aggregate([ 
     { $project: { 
      doc: "$$ROOT", 
      likedBySelf: { 
       $cond: { 
        "if": { "$setIsSubset": [ 
         [USERID], 
         "$likedBy" 
        ]}, 
        "then": true, 
        "else": false 
       } 
      } 
     }} 
    ]); 
0

@tskippe你可以使用的方法类似下面的处理是否帖子是由用户喜欢自己和你想随时随地调用该函数。

var processIsLiked = function(postId, userId, doc, next){ 
    var q = Post.find({post_id: postId}); 
    q.lean().exec(function(err,res){ 
    if(err) return utils.handleErr(err, res); 
    else { 
     if(_.find(doc.post.likedBy,userId)){ //if LikedBy array contains the user 
      doc.post.isLiked = true; 
     } else { 
      doc.post.isLiked = false; 
     } 
     }); 
     next(doc); 
    } 
    }); 
} 

因为你正在使用q.lean()你不需要实际存留数据。您需要处理它,在帖子中添加isLiked字段并发送回应。 **请注意,我们正在直接制作doc。此外,你会叮嘱它接受包含帖子数组的文档并迭代它,并为每个帖子附加一个isLiked字段。

+0

如果我的情况是,我只需要标记一个单一的职位,这将是有益的。但我想做一个查询来获得多个文档,并在同一时间标记它们。 – tskippe

+0

如果是这样的话,正如我在我的回答中所说的,你可以稍微微调一下。获取所有需要的文档,我猜你会有一系列的文章。然后将这个postIds数组作为参数传递给进程函数,您将返回具有“isLiked”附加字段的同一个帖子数组,作为true或false。如果这是需要的。 var q = Post。find({post:{$ in:postIds});然后执行查询,你可以对结果运行一个forEach循环,并对每个对象应用isLiked检查 –

+0

是的,这也可以工作,但我想如果你可以在一个查询中做到这一切。检查我的答案,我发布了一个聚合函数,可以满足我的需求。 – tskippe