【问题标题】:Mongodb: Populate based on conditionMongodb:根据条件填充
【发布时间】:2021-06-15 17:43:16
【问题描述】:

我有一些集合,我正在尝试将日志对象转换为其详细信息(使用 populate)。

Companies(公司及其用户):

[
    {
        _id: "comp123",
        companyId: "compName123",
        users: [
            { user: "user111", status: "active"},
            { user: "user222", status: "active"},
        ]
    },
    {
        _id: "comp456",
        name: "compName456",
        users: [
            { user: "user333", status: "active"}
        ]
    },
    {
        _id: "comp789",
        name: "compName789",
        users: [
            { user: "user444", status: "inactive"}
        ]
    },
]

Users:

[
    {_id: "user111", firstName: "userName111"},
    {_id: "user222", firstName: "userName222"},
    {_id: "user333", firstName: "userName333"},
    {_id: "user444", firstName: "userName444"},
]

我正在尝试将log 集合转换为数据。

examples:

对于log的第一个对象:

{
   companyId: "comp123",
   actionDetails: [
      entities: [
         { id: "user111", entityType: "User"}
      ]
   ]
},

我希望它返回:

{
    companyId: {_id: "comp123", name: "compName123"}, // taken from companies
    userId: { _id: "user111", firstName: "userName111"}, // taken from users
    // Does company=comp123 that has a user with user=user111 and status=active exist?
    isUserActiveInCompany: true
}

另一个日志示例:

{
    companyId: "comp456",
    actionDetails: [
        entities: [
            { id: "user444", entityType: "User"}
        ]
    ]
}

输出是:

{
    companyId: {_id: "comp456", name: "compName456"}, // taken from companies
    userId: { _id: "user444", firstName: "userName444"}, // taken from users
    isUserActiveInCompany: false // Does company=comp456 that has a user with user=user444 and status=active exist?
}

最后一个重要的日志示例:

{
    companyId: "comp789",
    actionDetails: [
        entities: [
            { id: "attr333", entityType: "Attribute"}
        ]
    ]
}

输出:

{
    companyId: {_id: "comp789", name: "compName789"}, // taken from companies
    userId: {}, // taken from users (entityType is Attribute so we ignore it)
    isUserActiveInCompany: null // entityType is Attribute so we ignore it
}

如果有用户 444 的 comp789 日志,isUserActiveInCompany 应该为 false(因为用户在他的公司中不活跃)。

目前,我这样做:

populate([
    {
        path: "actionDetails.entities.id",
        select: "id firstName",
    },
    {
        path: "companyId",
        select: "name",
    },
]

任何帮助表示赞赏!

【问题讨论】:

  • 我的问题清楚了吗?谢谢。
  • 其实对我来说有点难以理解。请提供来自集合和预期输出的示例输入
  • @hhharsha36,我现在添加。谢谢。
  • actionDetailsentities 都是日志集合中的数组吗?
  • @hhharsha36,是的。

标签: mongodb mongoose-populate


【解决方案1】:

将以下聚合管道代码转换为 Mongoose 等效项以获得您想要的输出。

db.log.aggregate([
  {
    '$match': {
      // <-- I highly recommend that you use a `$match` condition since there are 2 lookup operators in the aggregation which will significantly increase execution time.
    }
  },
  {
      '$lookup': {
      'from': 'Companies',
      'let': {'cId': '$companyId'},
      'pipeline': [
        {
          '$match': {
            '$expr': {
              '$eq': ['$_id', '$$cId']
            }
          }
        },
        {
          "$project": {
            'company': {
              "_id": "$_id",
              "companyName": "$companyId"
            },
            'users': {
              "$filter": {
                'input': "$users",
                'as': "usr",
                'cond': {
                  "$eq": ["$$usr.status", "active"],
                },
              },
            },
          }
        },
      ],
      'as': 'companyDetails'
    }
  },
  {
    '$unwind': {
      'path': "$actionDetails",
    }
  }, 
  {
    '$unwind': {
    'path': "$actionDetails.entities",
    }
  }, 
  {
    '$lookup': {
      'from': 'Users',
      'let': {"uId": "$actionDetails.entities.id"},
      'pipeline': [
        {
          "$match": {
            "$expr": {
              "$eq": ["$_id", "$$uId"],
            },
          },
        },
        {
          "$project": {
            "firstName": 1,
          },
        },
      ],
      'as': "userDetails",
    }
  },
  {
    '$project': {
      "companyId": {"$arrayElemAt": ["$companyDetails.company", 0]},
      "userId": {
        "_id": "$actionDetails.entities.id",
        "firstName": {"$arrayElemAt": ["$userDetails.firstName", 0]},
      },
      "isUserActiveInCompany": {
        "$switch": {
          "branches": [
            {
              'case': {
                "$ne": ["$actionDetails.entities.entityType", "User"]
              },
              'then': null,
            },
            {
              'case': {
                "$in": [
                  "$actionDetails.entities.id",
                  {
                    "$map": {
                      'input': {"$arrayElemAt": ["$companyDetails.users", 0]},
                      'as': "elem",
                      'in': "$$elem.user"
                    }
                  }
                ]
              },
              'then': true,
            },
          ],
          'default': false,
        }
      }
    }
  }
], {
  'allowDiskUse': true,
});

如果您想要每个阶段的完整解释和逻辑,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-06
    • 2020-09-06
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    相关资源
    最近更新 更多