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

DP_*_*DP_ 7 mongodb

我有两个收藏pagelikes。在这两个集合中都有 field 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
Run Code Online (Sandbox Code Playgroud)

我想过使用该$exists运算符,但在这里我读到它的含义与同名的 SQL 操作不同,我必须使用该$in运算符。

我可以

  1. 找出特定用户喜欢的所有页面并将它们保存在列表中
  2. 然后在 上运行查询page,这应该返回第一个页面,该页面不包含在列表中。

我正在犹豫是否以这种方式实现它,因为它对我来说似乎效率很低(我在步骤 2 中只需要一页,但为了获得该一页,我需要遍历用户的所有喜欢)。

Mic*_*rry 5

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

  1. 查找相关对象
  2. 用于$expr { $and: [] }将连接与附加约束结合起来
  3. 用于$limit: 1优化,因为我们只关心是否存在
  4. $match连接属性在哪里$exists: false
  5. 为了更好的措施,$project消除空集合

例如,要查询特定用户没有点赞的页面,请按如下方式构建管道:

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
    }
}])
Run Code Online (Sandbox Code Playgroud)

  • Hołyszewski 定律:每个 NoSQL DBMS 最终都会添加 SQL DBMS 的所有功能,但这些功能的使用和编码都极其困难。 (10认同)

Alb*_*elB 1

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

通常,在设置数据时,您不希望像这样标准化数据(用户、他们的喜好和页面的单独集合)。

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

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

获得点赞后,您将需要获得唯一的页面 ID 列表。您可以使用_.uniq()网上找到的方法或其他方法来做到这一点。

一旦获得唯一 page 的数组_id,您现在就可以使用 进行查询$nin

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

$nin接受一个数组,并将匹配具有不在数组中的值的任何内容。 您可以阅读此处了解更多详细信息。