【问题标题】:MongoDB query with fields from different collection使用来自不同集合的字段的 MongoDB 查询
【发布时间】:2020-04-25 01:54:58
【问题描述】:

我不知道如何构建执行此操作的查询:

我有一个用户集合,每个用户都有一个字段 userdata,其中包含一个字符串数组。 每个字符串都是另一个集合中其他文档(已经看过的新闻)的ObjectID的字符串。

我需要知道这个用户的用户名,来执行一个查询来获取所有新闻,但不是那些已经看过的新闻。

我认为$nin 运算符可以满足我的需要,但我不知道如何将它与来自另一个集合的数据混合。

Users
    user
        username: String
        userdata: Object
            news: Array of String

News
    news1
        _id: ObjectID
    news2
        _id: ObjectID

示例:

Users: [{
    username: 'mario',
    userdata: {
        news: ['10', '11']
    }
}]
News: [{
    _id: '10',
    content: 'hello world10'
},{
    _id: '11',
    content: 'hello world11'
},{
    _id: '12',
    content: 'hello world12'
}]

username(作为字符串)'mario' 传递给查询,我需要查询集合新闻并只返回带有_id '12' 的那个。

谢谢

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您需要运行$lookup with custom pipeline。没有用于聚合的 $nin,但您可以使用 $not$in。然后你也可以尝试$unwind$replaceRoot 将过滤后的News 提升到根级别:

    db.Users.aggregate([
        { $match: { username: "mario" } },
        {
            $lookup: {
                from: "News",
                let: { user_news: "$userdata.news" },
                pipeline: [{ $match: { $expr: { $not: { $in: [ "$_id", "$$user_news" ]  } } } }],
                as: "filteredNews"
            }
        },
        { $unwind: "$filteredNews" },
        { $replaceRoot: { newRoot: "$filteredNews" }}
    ])
    

    【讨论】:

    • 你会推荐这个而不是做 2 个不同的查询吗?
    • 使用 $lookup 应该更快,如果你真的需要两个查询,那么你可以使用$nin 但我会尝试使用一个
    • 我已经尝试过你建议的这个,但无论如何它都会返回所有新闻。可能是因为我将对象 ID 作为字符串存储在用户数据中吗?如果是这样,如何使它工作?
    • @Mattia 类型需要相同。在$_id 上使用 $toString 或 $toObjectId 以一种或另一种方式进行转换
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 2015-02-17
    • 2020-05-31
    • 2022-01-09
    相关资源
    最近更新 更多