Mongodb:根据条件填充

问题描述

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

Companies(公司及其用户):

[
    {
        _id: "comp123",companyId: "compName123",users: [
            { user: "user111",status: "active"},{ user: "user222",]
    },{
        _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",// 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",// 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
}

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

目前,我这样做:

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

感谢任何帮助!

解决方法

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

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","isUserActiveInCompany": {
        "$switch": {
          "branches": [
            {
              'case': {
                "$ne": ["$actionDetails.entities.entityType","User"]
              },'then': null,{
              'case': {
                "$in": [
                  "$actionDetails.entities.id",{
                    "$map": {
                      'input': {"$arrayElemAt": ["$companyDetails.users",'as': "elem",'in': "$$elem.user"
                    }
                  }
                ]
              },'then': true,'default': false,}
      }
    }
  }
],{
  'allowDiskUse': true,});

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