MongoDB:将不同的字段用相同的值进行分组。

问题描述 投票:0回答:1

我需要对一个mongodb集合进行聚合。但我找不到正确的聚合流水线。

事实上,我需要得到Ids的 不同文件field1 == field2 (字段1与字段2不在同一文档中)。

例如我想查找所有的文档,当源文件与目标文件相同时。document1.fieldX == document2.fieldY

这是关于通过端口号查找目标服务器。

示例文档。

[ 
  {
    id: 444,
    name: 'Server 1'
    portSource: 1,
    portTarget: 7,
  },
  {
    id: 555,
    name: 'Server 2'
    portSource: 7,
    portTarget: 1
  },
  {
    id: 666,
    name: 'Server 3'
    portSource: 1,
    portTarget: 8
  },
   {
    id: 777,
    name: 'Server 4'
    portSource: 3,
    portTarget: 5
  },
 {
    id: 888,
    name: 'Server 5'
    portSource: 5,
    portTarget: 3
  },
]

希望的输出。

[
 {
  portSource: 1, portTarget: 7, sourceId : 444, targetId: 555
 },
 {
  portSource: 3, portTarget: 5, sourceId : 777, targetId: 888
 }
]


编辑。

注1: 服务器: id: 666 不返回,因为有其他服务器与他的目标端口匹配。

注2: 正确的输出也可以是这样的。

(反向目标源)

[
 {
  portSource: 7, portTarget: 1, sourceId : 555, targetId: 444
 },
 {
  portSource: 5, portTarget: 3, sourceId : 888, targetId: 777
 }
]

或者它可以包含两次(正常方式和反向)。

[
 {
  portSource: 1, portTarget: 7, sourceId : 444, targetId: 555
 },
 {
  portSource: 7, portTarget: 1, sourceId : 555, targetId: 444
 },
 {
  portSource: 3, portTarget: 5, sourceId : 777, targetId: 888
 },
 {
  portSource: 5, portTarget: 3, sourceId : 888, targetId: 777
 }
]
mongodb mongoose mongodb-query aggregation-framework document
1个回答
0
投票

你需要尝试 $lookup 在同一集合上的聚合管道阶段。

db.collectionName.aggregate([
    {
      $lookup: {
        from: "collectionName", /** Same collection name */
        let: { portSource: "$portSource" }, /** create a local variable 'portSource' from value of 'portSource' of current doc in lookup stage */
        pipeline: [ /** pipline helps to execute aggregation stages */
          { $match: { $expr: { $and: [ { $eq: [ "$portTarget", "$$portSource" ] }, { $eq: [ "$portSource", "$$portTarget" ] } ] } } }, /** match to filter docs */
          { $project: { id: 1, _id: 0 } } /** project only `id` of matched doc in a new field `targetId` */
        ],
        as: "targetId" /** will be an array, will be empty if none matches (In your case, mostly will be empty or array of single object) */
      }
    },
    /** Only Pairs will have `targetId` non-empty, removing docs where `targetId` array is empty */
    { $match: { targetId: { $ne: [] } } },
    /** create a new field `sourceId` from value of existing field `id`,
     *  re-create `targetId` from value of first elements `id` field in `targetId` array,
     *  You won't find this field for the doc where none of the docs matches for given `portSource` */
    {
      $addFields: { sourceId: "$id", targetId: {  $arrayElemAt: [ "$targetId.id", 0 ] } }
    },
    /** Removing un-necessary field */
    {
      $project: { id: 0 }
    }
  ])

测试。 mongoplayground

© www.soinside.com 2019 - 2024. All rights reserved.