MongoDB多个集合连接并进行分组统计。

huangapple go评论57阅读模式
英文:

mongodb multiple collection join with groupby

问题

以下是你提供的内容的翻译:

我是MongoDB的新手,但我正在尝试根据文档类型(type_id)聚合数据。我有以下集合。

items集合

{
    "_id": "BE05332051E0AD282",
    "type_id": "684EB00155D031225", //组织或书籍或个人
    "name": "Owi Student Union",
    "structure": {
        "organization_active_status": "Inactive",
        "country": "USA"
    },
    "hash": "59E48A8C3F7B20",
    "geometry": {
        "type": "Point",
        "coordinates": [
            -85.48172999999997,
            32.60746000000006
        ]
    },
    "geometry_confidence": 0.0,
    "has_geometry": true,
    "is_node": false,
    "groupids": [
        "DE05332041E0A4978"
    ]
}

tuples集合

{
    "_id": "0E05333051E0A02E7",
    "source_id": "BE05332051E0AD282",
    "destination_id": "9E05332051E0AF344",
    "edge_id": "DE05332051E0A3B5B",
    "direction": NumberInt(1),
    "changed": true
}
{
    "_id": "0E05333061E0A02E8",
    "source_id": "BE05332051E0AD282",
    "destination_id": "0E05333051E0A02E7",
    "edge_id": "DE05332051E0A3B5B",
    "direction": NumberInt(1),
    "changed": true
}

types集合

{
    "_id": "684EB00155D031225",
    "name": "Organization"
}
{
    "_id": "BE0532A041E0AC077",
    "name": "Book"
}

1)items集合包含所有类型的文档,包括组织、书籍,可以根据type_id进行区分。
2)每个组织可能有多本书籍和个人。

关系:

1)tuples.source_id = items._id
2)tuples.destination_id = items._id
3)items.type_id = type._id

我正在尝试像这样聚合数据,但无法获得完整的结果。

db.tuples.aggregate([
    {
        $lookup: {
            from: "items",
            localField: "destination_id",
            foreignField: "_id",
            as: "source"
        }
    },
    {
        $match: {
            "source_id": "5BD5A377499D406EE05332051E0A93C2",
            "source.type_id": "43B369EDE96A4876E0532A041E0A995A"
        }
    }
]);

有人可以帮助我如何创建最终结果,类似于以下内容:

组织

{
    "_id": "BE05332051E0AD282",
    "type_id": "684EB00155D031225", //组织
    "chapters": {
        "章节列表(从item集合中获取的文档)"
    },
    "books": {
        "书籍列表(从item集合中获取的文档)"
    }
}

我真的很感谢任何形式的帮助或建议,谢谢!

英文:

I am noobie in mongodb,
<br>but I am trying to aggregate data based on type of document(type_id)
I have following collections

items<br>

{
    &quot;_id&quot; : &quot;BE05332051E0AD282&quot;,
    &quot;type_id&quot; : &quot;684EB00155D031225&quot;,//Organization or Book or Person
    &quot;name&quot; : &quot;Owi Student Union&quot;,
    &quot;structure&quot; : {
        &quot;organization_active_status&quot; : &quot;Inactive&quot;,
        &quot;country&quot; : &quot;USA&quot;
    },
    &quot;hash&quot; : &quot;59E48A8C3F7B20&quot;,
    &quot;geometry&quot; : {
        &quot;type&quot; : &quot;Point&quot;,
        &quot;coordinates&quot; : [
            -85.48172999999997,
            32.60746000000006
        ]
    },
    &quot;geometry_confidence&quot; : 0.0,
    &quot;has_geometry&quot; : true,
    &quot;is_node&quot; : false,
    &quot;groupids&quot; : [
        &quot;DE05332041E0A4978&quot;
]
}

tuples<br>

{
    &quot;_id&quot; : &quot;0E05333051E0A02E7&quot;,
    &quot;source_id&quot; : &quot;BE05332051E0AD282&quot;,
    &quot;destination_id&quot; : &quot;9E05332051E0AF344&quot;,
    &quot;edge_id&quot; : &quot;DE05332051E0A3B5B&quot;,
    &quot;direction&quot; : NumberInt(1),
    &quot;changed&quot; : true
}
{
    &quot;_id&quot; : &quot;0E05333061E0A02E8&quot;,
    &quot;source_id&quot; : &quot;BE05332051E0AD282&quot;,
    &quot;destination_id&quot; : &quot;0E05333051E0A02E7&quot;,
    &quot;edge_id&quot; : &quot;DE05332051E0A3B5B&quot;,
    &quot;direction&quot; : NumberInt(1),
    &quot;changed&quot; : true
}

types<br>

{
    &quot;_id&quot; : &quot;684EB00155D031225&quot;,
    &quot;name&quot; : &quot;Organization&quot;
},
{
    &quot;_id&quot; : &quot;BE0532A041E0AC077&quot;,
    &quot;name&quot; : &quot;Book&quot;
}
  1. items collection contain all type of document for organization, books and can be differentiate on type_id
  2. each organizations may have multiple books, person

relations

1) tuples.source_id = items._id
2) tuples.destination_id = items._id
3) items.type_id = type._id

I am trying aggregate data like this, but unable to get complete result

db.tuples.aggregate([
    {
        $lookup:{
            from: &quot;items&quot;,
            localField: &quot;destination_id&quot;,
            foreignField: &quot;_id&quot;,
            as: &quot;source&quot; 
        }
    },
    {
        $match:{
           &quot;source_id&quot;:&quot;5BD5A377499D406EE05332051E0A93C2&quot;,
           &quot;source.type_id&quot; : &quot;43B369EDE96A4876E0532A041E0A995A&quot;
        }
    }
]);

Could any one help me on how can I create final result like this

Organizations

{
    &quot;_id&quot; : &quot;BE05332051E0AD282&quot;,
    &quot;type_id&quot; : &quot;684EB00155D031225&quot;,//Organization
    chapters : {
     &quot;list of chapter(documents from item collection)&quot;
    },
    books : { 
    &quot;list of books(documents from item collection)&quot;
    }
}

I would really appreciate any kind of help or suggestion, Thanks

答案1

得分: 1

你可以使用以下聚合管道来实现这个功能。你可以在这里运行它,
https://mongoplayground.net/p/H2Ygqgjp2f5

db.items.aggregate([
  {
    "$match": {
      "type_id": "684EB00155D031225"
    }
  },
  {
    "$lookup": {
      from: "tuples",
      localField: "_id",
      foreignField: "source_id",
      as: "tuples"
    }
  },
  {
    "$lookup": {
      from: "items",
      let: {
        destination_ids: "$tuples.destination_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                "$_id",
                "$$destination_ids"
              ]
            },
            "type_id": "BE0532A041E0AC077"
          }
        }
      ],
      as: "books"
    }
  },
  {
    "$lookup": {
      from: "items",
      let: {
        destination_ids: "$tuples.destination_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                "$_id",
                "$$destination_ids"
              ]
            },
            "type_id": "BE0532A041E0AC087"
          }
        }
      ],
      as: "persons"
    }
  },
  {
    "$project": {
      "_id": 1,
      "type_id": 1,
      "name": 1,
      "books": 1,
      "persons": 1
    }
  }
])

这将返回如下结果。

[
  {
    "_id": "BE05332051E0AD282",
    "books": [
      {
        "_id": "9E05332051E0AF344",
        "name": "Test Book 1",
        "type_id": "BE0532A041E0AC077"
      }
    ],
    "name": "Owi Student Union",
    "persons": [
      {
        "_id": "0E05333051E0A02E7",
        "name": "Test Person 1",
        "type_id": "BE0532A041E0AC087"
      }
    ],
    "type_id": "684EB00155D031225"
  }
]

但我建议您重新考虑您的数据库设计,因为您正在使用NoSQL数据库,您应该能够嵌入文档并拥有类似树结构的结构。希望这有所帮助。

英文:

You can achieve this with aggregation pipeline as below. You can run it here,
https://mongoplayground.net/p/H2Ygqgjp2f5

    db.items.aggregate([
  {
    &quot;$match&quot;: {
      &quot;type_id&quot;: &quot;684EB00155D031225&quot;
    }
  },
  {
    &quot;$lookup&quot;: {
      from: &quot;tuples&quot;,
      localField: &quot;_id&quot;,
      foreignField: &quot;source_id&quot;,
      as: &quot;tuples&quot;
    }
  },
  {
    &quot;$lookup&quot;: {
      from: &quot;items&quot;,
      let: {
        destination_ids: &quot;$tuples.destination_id&quot;
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                &quot;$_id&quot;,
                &quot;$$destination_ids&quot;
              ]
            },
            &quot;type_id&quot;: &quot;BE0532A041E0AC077&quot;
          }
        }
      ],
      as: &quot;books&quot;
    }
  },
  {
    &quot;$lookup&quot;: {
      from: &quot;items&quot;,
      let: {
        destination_ids: &quot;$tuples.destination_id&quot;
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                &quot;$_id&quot;,
                &quot;$$destination_ids&quot;
              ]
            },
            &quot;type_id&quot;: &quot;BE0532A041E0AC087&quot;
          }
        }
      ],
      as: &quot;persons&quot;
    }
  },
  {
    &quot;$project&quot;: {
      &quot;_id&quot;: 1,
      &quot;type_id&quot;: 1,
      &quot;name&quot;: 1,
      &quot;books&quot;: 1,
      &quot;persons&quot;: 1
    }
  }
])

this would return a result as this.

  [
  {
    &quot;_id&quot;: &quot;BE05332051E0AD282&quot;,
    &quot;books&quot;: [
      {
        &quot;_id&quot;: &quot;9E05332051E0AF344&quot;,
        &quot;name&quot;: &quot;Test Book 1&quot;,
        &quot;type_id&quot;: &quot;BE0532A041E0AC077&quot;
      }
    ],
    &quot;name&quot;: &quot;Owi Student Union&quot;,
    &quot;persons&quot;: [
      {
        &quot;_id&quot;: &quot;0E05333051E0A02E7&quot;,
        &quot;name&quot;: &quot;Test Person 1&quot;,
        &quot;type_id&quot;: &quot;BE0532A041E0AC087&quot;
      }
    ],
    &quot;type_id&quot;: &quot;684EB00155D031225&quot;
  }
]

But I would suggest you rethink your database design, since you are using a nosql database you should be able to embed documents and have a tree like structure. Hope this helps.

huangapple
  • 本文由 发表于 2023年6月8日 15:00:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76429336.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定