下面列出了这两个集合

orders: [
  {
    "_id": "64355c928dcce8cdf4b9c7d2",
    "destinations": [
      {
        "ship_to_id": "64355c92af10d37993473e12", // mongoose id from locations collection
        "sold_to_id": "64355c92a57d8b29412a1cc2" // mongoose id from locations collection
      },
      {
        "ship_to_id": "64355c92a57d8b29412a1cc2",
        "sold_to_id": "64355c92ed8af3f7cd7199b2"
      },
      {
        "ship_to_id": "64355c92256aa652e6c3fdc5",
        "sold_to_id": "64355c924f9a2fcafa90daed"
      }
    ],
    "contact_details": [
      {
        "ship_to_ref": "aaa",
        "sold_to_ref": "bbb",
        "contact_email": "a@gmail.com",
      },
      {
        "ship_to_ref": "bbb",
        "sold_to_ref": "ccc",
        "contact_email": "b@gmail.com"
      },
      {
        "ship_to_ref": "ddd",
        "sold_to_ref": "eee",
        "contact_email": "c@gmail.com",
      }
    ]
  },
  {
    "_id": "64355c92bf25e54cf901be39",
    "destinations": [
      {
        "ship_to_id": "64355c92af10d37993473e12",
        "sold_to_id": "64355c92a57d8b29412a1cc2"
      },
      {
        "ship_to_id": "64355c92a57d8b29412a1cc2",
        "sold_to_id": "64355c92ed8af3f7cd7199b2"
      },
      {
        "ship_to_id": "64355c92af10d37993473e12",
        "sold_to_id": "64355c92256aa652e6c3fdc5"
      }
    ],
    "contact_details": [
      {
        "ship_to_ref": "aaa",
        "sold_to_ref": "bbb",
        "contact_email": "a@gmail.com",
      },
      {
        "ship_to_ref": "bbb",
        "sold_to_ref": "ccc",
        "contact_email": "b@gmail.com",
      },
      {
        "ship_to_ref": "aaa",
        "sold_to_ref": "ddd",
        "contact_email": "d@gmail.com",
      }
    ]
  },
  {
    "_id": "64355c921445785f4b50040e",
    "destinations": [
      {
        "ship_to_id": "64355c92af10d37993473e12",
        "sold_to_id": "64355c92a57d8b29412a1cc2"
      },
      {
        "ship_to_id": "64355c92af10d37993473e12",
        "sold_to_id": "64355c92ed8af3f7cd7199b2"
      }
    ],
    "contact_details": [
      {
        "ship_to_ref": "aaa",
        "sold_to_ref": "bbb",
        "contact_email": "a@gmail.com",
      },
      {
        "ship_to_ref": "aaa",
        "sold_to_ref": "ccc",
        "contact_email": "e@gmail.com",
      },
    ]
  }
]

locations: [
  {
    "_id": "64355c92af10d37993473e12",
    "reference_id": "aaa"
  },
  {
    "_id": "64355c92a57d8b29412a1cc2",
    "reference_id": "bbb"
  },
  {
    "_id": "64355c92ed8af3f7cd7199b2",
    "reference_id": "ccc"
  },
  {
    "_id": "64355c92256aa652e6c3fdc5",
    "reference_id": "ddd"
  },
  {
    "_id": "64355c924f9a2fcafa90daed",
    "reference_id": "eee"
  },
]

Now what I want to achieve is write an aggregate query that groups me all the indents based on same ship_to, sold_to 和 contact_email (Note: to verify if thats a valid ship_to 和 sold_to we need to lookup from the locations collection using the ship_to_idsold_to_id, retrieve the respective reference_id 's 和 then compare it with the ship_to_refsold_to_ref that is available in contact details) such that the query result will be like

[{
  _id: {
    ship_to_ref: "aaa",
    sold_to_ref: "bbb",
    ship_to_id:"64355c92af10d37993473e12"
    sold_to_id:"64355c92a57d8b29412a1cc2"
    contact_email: "a@gmail.com"
   },
   orders: [
     { "_id": "64355c928dcce8cdf4b9c7d2", ... },
     { "_id": "64355c92bf25e54cf901be39", ... },
     { "_id" : "64355c921445785f4b50040e", ...}
   ],
 },
 {
  _id: {
    ship_to_ref: "bbb",
    sold_to_ref: "ccc",
    ship_to_id:"64355c92a57d8b29412a1cc2",
    sold_to_id:"64355c92ed8af3f7cd7199b2",
    contact_email: "b@gmail.com"
   },
   orders: [
     { "_id": "64355c928dcce8cdf4b9c7d2", ... },
     { "_id": "64355c92bf25e54cf901be39", ... },
   ],
 },
 {
  _id: {
    ship_to_ref: "ddd",
    sold_to_ref: "eee",
    ship_to_id: "64355c92256aa652e6c3fdc5",
    sold_to_id: "64355c924f9a2fcafa90daed",
    "contact_email": "c@gmail.com",
   },
   orders: [
     { "_id": "64355c928dcce8cdf4b9c7d2", ... }
   ],
 },
{
  _id: {
    ship_to_ref: "aaa",
    sold_to_ref: "ddd",
    ship_to_id: "64355c92af10d37993473e12",
    sold_to_id: "64355c92256aa652e6c3fdc5",
    contact_email: "d@gmail.com",
   },
   orders: [
     { "_id": "64355c92bf25e54cf901be39", ... }
   ],
 },
{
  _id: {
    ship_to_ref: "aaa",
    sold_to_ref: "ccc",
    ship_to_id: "64355c92af10d37993473e12",
    sold_to_id: "64355c92ed8af3f7cd7199b2",
    contact_email: "e@gmail.com",
   },
   orders: [
     { "_id": "64355c921445785f4b50040e", ... }
   ],
 },
]

下面是我try 过的聚合查询

[{
  $match: {
    contact_details: { $exists: true },
  },
},
{ $unwind: '$destinations' },
{ $unwind: '$contact_details'},
{
  $group: {
    _id: {
      sold_to_id: '$destinations.sold_to_id',
      ship_to_id: '$destinations.ship_to_id',
    }
    orders: {
      $push: {
        id: '$order_no', // order_no is an attribute from an order object
        contact_details: '$contact_details',
        destinations: '$destinations', // should contain all the destinations that were there initially inside an order entry
      },
    },
    type: { $first: { type: '$destinations.type' } },
  },
}]

but not sure how to incorporate a lookup 和 do the ref comparison 和 email check. Need help.

提前谢谢你

推荐答案

一个选项是在unwind之前设置为$map,因此您只能使用unwind一次,并使用$indexOfArray以匹配$lookup之后的引用:

db.orders.aggregate([
  {$match: {contact_details: {$exists: true}}},
  {$project: {
      del: {$map: {
          input: {$range: [0, {$size: "$contact_details"}]},
          in: {
            destination: {$arrayElemAt: ["$destinations", "$$this"]},
            contact: {$arrayElemAt: ["$contact_details", "$$this"]},
            destinations: "$destinations"
          }
      }}
  }},
  {$unwind: "$del"},
  {$group: {
      _id: {
        sold_to_id: "$del.destination.sold_to_id",
        ship_to_id: "$del.destination.ship_to_id"
      },
      contact_email: {$first: "$del.contact.contact_email"},
      orders: {$push: {
          _id: "$_id", 
          contact_details: "$del.contact",
          destinations: "$del.destinations"
      }}
  }},
  {$set: {locations: ["$_id.sold_to_id", "$_id.ship_to_id"]}},
  {$lookup: {
      from: "locations",
      localField: "locations",
      foreignField: "_id",
      as: "locations"
  }},
  {$project: {
      "_id.ship_to_id": "$_id.ship_to_id",
      "_id.sold_to_id": "$_id.sold_to_id",
      "_id.contact_email": "$contact_email",
      "_id.ship_to_ref": {$getField: {
          input: {$arrayElemAt: [
              "$locations",
              {$indexOfArray: ["$locations._id", "$_id.ship_to_id"]}
          ]},
          field: "reference_id"
      }},
      "_id.sold_to_ref": {$getField: {
          input: {$arrayElemAt: [
              "$locations",
              {$indexOfArray: ["$locations._id", "$_id.sold_to_id"]}
          ]},
          field: "reference_id"
      }},
      orders: 1
  }}
])

看看它在playground example号公路上是如何工作的

Javascript相关问答推荐

如何使用JavaScript向html元素添加样式

如何在dataTables PDF输出中正确渲染字形?

如何避免使用ajax在Vue 3合成API中重定向

如何指定1条记录1个表?

如何循环访问对象数组并以关键值形式获得结果?

如何在JavaScript中在文本内容中添加新行

在React中获取数据后,如何避免不必要的组件闪现1秒?

在Angular中将样式应用于innerHTML

Redux查询多个数据库Api reducerPath&

函数返回与输入对象具有相同键的对象

我的服务工作器没有连接到我的Chrome扩展中的内容脚本.我该怎么解决这个问题?

当Redux提供程序访问Reduxstore 时,可以安全地从Redux提供程序外部调用钩子?

这个值总是返回未定义的-Reaction

映射类型定义,其中值对应于键

如何使用JS创建一个明暗功能按钮?

如何在Java脚本中对数据进行签名,并在PHP中验证签名?

如何更改Html元素S的 colored颜色 ,然后将其褪色为原始 colored颜色

有没有办法通过使用不同数组中的值进行排序

如何在Web项目中同步语音合成和文本 colored颜色 更改

如何在加载页面时使锚定标记成为焦点