如何在MongoDB中运行NOT EXISTS查询?

时间:2014-08-27 20:58:11

标签: mongodb

我有两个集合pagelikes。在两个集合中都有字段pageIdlikes也有字段userName

如果likes集合包含pageId / userName对,则表示该页面与特定用户相似。

如何运行一个返回任何一个页面的查询,这个页面不是特定用户喜欢的?

在SQL中,这将是这样的:

SELECT *
FROM page
WHERE NOT EXISTS (SELECT 'a' FROM likes WHERE (likes.pageId = page.pageId) AND (likes.userName = 'userName'))
LIMIT 1

我考虑过使用$exists运算符但here我已经读过它的含义与具有相同名称的SQL操作不同,我必须使用$in操作

我可以

  1. 查找特定用户喜欢的所有页面并将其保存在列表中
  2. 然后在page上运行查询,该查询应返回未包含在列表中的页面。
  3. 我很犹豫以这种方式实现它,因为它对我来说似乎效率很低(我在步骤2中只需要一个页面,但要获得一个页面,我需要遍历所有用户的喜欢)。

2 个答案:

答案 0 :(得分:1)

所以我误解了最初的问题,但要回答,使用MongoDB在单个查询中没有任何方法可以进行该查询。

通常在设置数据时,您不希望像这样规范化数据(针对用户,他们的喜欢和页面的单独集合)。

因此,第一步是根据我们正在寻找的用户获取一个独特的喜欢列表。

db.likes.find({personId: <your_id>}, function(e, allLikes) {/* more */})

获得喜欢之后,您会想要获得唯一的网页ID列表。您可以使用_.uniq()或在线找到的其他方法来实现此目的。

获得一系列唯一页面_id后,您现在可以使用$nin进行查询。

db.pages.find({_id: { $nin: uniquePageIds } }, function(e, allUnlikedPages) { /* your logic */ })

$nin接受一个数组,并匹配数组中不具有值的任何内容。 You can read here for more details.

答案 1 :(得分:0)

在3.6版本中,我们有一个新的$ lookup管道语法,允许您在相关文档上执行管道。您可以使用它来查找符合您特定条件的相关文档。将其与更多步骤相结合,您可以构建NOT EXISTS查询。

  1. 查找相关对象
  2. 使用$expr { $and: [] }将联接与其他约束相结合
  3. 使用$limit: 1进行优化,因为我们只关心是否存在
  4. $match其中,加入属性$exists: false
  5. 为了更好的衡量,$project消除空集合
  6. 例如,要查询特定用户没有喜欢的页面,请按如下方式构建管道:

    db.page.insertOne({ pageId: 1 })
    db.page.insertOne({ pageId: 2 })
    db.page.insertOne({ pageId: 3 })
    db.likes.insertOne({ pageId: 1, userName: "Pinky" })
    db.likes.insertOne({ pageId: 2, userName: "Pinky" })
    db.likes.insertOne({ pageId: 2, userName: "Brain" })
    db.likes.insertOne({ pageId: 3, userName: "Brain" })
    
    db.page.aggregate([{
        "$lookup": {
            "from": "likes",
            "let": {
                "pageId": "$pageId"
            },
            "pipeline": [{
                "$match": {
                    "$expr": {
                        "$and": [
                            { "$eq": [ "$pageId", "$$pageId" ] },
                            { "$eq": [ "$userName", "Pinky" ] }
                        ]
                    }
                }
            }, {
                "$limit": 1
            }],
            "as": "likes"
        }
    }, {
        "$match": {
            "likes.pageId": { "$exists": false }
        }
    }, {
        "$project": {
            "likes": false
        }
    }])