【问题标题】:Mongodb aggregate to return result only if the lookup field has length仅当查找字段具有长度时,Mongodb 才聚合返回结果
【发布时间】:2021-09-08 12:22:14
【问题描述】:

我有两个集合 usersprofiles。我正在使用以下查询实现搜索:

User.aggregate(
      [
        { 
          $match: { 
          _id: { $ne: req.user.id },
          isDogSitter: { $eq: true },
          profileId: { $exists: true }
        }},
        {
          $project: {
            firstName: 1,
            lastName: 1,
            email: 1,
            isDogSitter: 1,
            profileId: 1,
        }},
        {
          $lookup: {
            from: "profiles",
            pipeline: [
              {
                $project: {
                  __v: 0,
                  availableDays: 0,
              }},
              {
                $match: {
                  city: search
              }}
            ],
            as: "profileId",
        }}
      ],
      (error, result) => {
        console.log("RESULT ", result);
      }
    );

这样做是它在profiles 集合中搜索city,当没有搜索匹配时,profileId 变成一个空数组。我真正想要的是,如果profileId 是一个空数组,那么我也不想返回文档中的其他字段。它应该清空数组。以下是我当前返回的结果。

RESULT  [
  {
    _id: 60cabe38e26d8b3e50a9db21,      
    isDogSitter: true,
    firstName: 'Test',
    lastName: 'Sitter',
    email: 'test@user.com',
    profileId: []
  }
]

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    $lookup 管道阶段之后添加$match 管道阶段和 在那里添加空数组条件检查。

    User.aggregate(
          [
            { 
              $match: { 
              _id: { $ne: req.user.id },
              isDogSitter: { $eq: true },
              profileId: { $exists: true }
            }},
            {
              $project: {
                firstName: 1,
                lastName: 1,
                email: 1,
                isDogSitter: 1,
                profileId: 1,
            }},
            {
              $lookup: {
                from: "profiles",
                pipeline: [
                  {
                    $project: {
                      __v: 0,
                      availableDays: 0,
                  }},
                  {
                    $match: {
                      city: search
                  }}
                ],
                as: "profileId",
            }}
            {
              $match: {  // <-- Newly added $match condition
                "profileId": {"$ne": []}
              },
            },
          ],
          (error, result) => {
            console.log("RESULT ", result);
          }
        );
    

    【讨论】:

    • 谢谢,我不知道,我们可以多次使用$match。目前,我正在查看所有文档以查找搜索结果,您知道我是否只想将一个文档附加到用户集合并仅搜索该文档。我在用户集合中有profileId 字段,他引用了profiles 集合的文档。
    • @GurkiranSingh 您可以根据需要多次使用任何管道阶段。来到嵌入部分,最好将所有profiles文档嵌入到user集合中,如果1.它们之间是一对多的关系,2.用户的个人资料数量不会超过100, 3. 将定期执行用户到个人资料查找操作。这是主观的,完全取决于您正在构建的应用程序,因此如果没有您的应用程序知识,我很难建议一种方法。希望这对您有所帮助。
    • 感谢您的意见。我正在查看$lookup 文档,我们可以使用localFieldforeignField 方法在profilesusers 之间建立一对一的关系,但是它不允许你在上面使用管道,就像我的情况$match。对于我的应用程序,一个特定的用户文档只有一个特定的配置文件。你能建议任何方法吗?
    • 如果用户和个人资料是一对一的关系,那么最好将profile 数据作为子文档嵌入到user 集合中。它将为您节省大量时间(因为$lookup 操作很昂贵)并且您的数据和应用程序的工作将不那么复杂。附言您可以使用 letpipeline 选项而不是 localField foreignField 方法对 $lookup 执行其他操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    • 2020-08-11
    相关资源
    最近更新 更多