MongoDB(27) - 集計処理(aggregate)⑧コレクション結合

今回は、コレクションの結合を行います。

サンプルデータ

以前用意した会社の部、課、従業員データを使用します。

集計処理(aggregate)①データ準備 - https://ailog.site/2021/09/02/2021/0902/

コレクションの結合

$lookupを使うと、コレクションの結合を行うことができます。

従業員コレクション(employee)と課コレクション(division)を結合します。

設定値の意味は下記の通りです。

  • from
    結合先のコレクション名
  • localField
    結合元のフィールド名
  • foreignField
    結合先のフィールド名
  • as
    結合先コレクションの別名

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.employee.aggregate([
{$lookup:{
from: "division",
localField:"k_id",
foreignField:"k_id",
as: "division_docs"
}}
])
{ "_id" : ObjectId("612f07f568110fe533ed9d21"), "e_id" : "emp001", "k_id" : "ka1", "p_id" : "po1", "name" : "高山", "age" : 31, "salary" : 400000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d19"), "k_id" : "ka1", "b_id" : "bu1", "name" : "総務課" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d22"), "e_id" : "emp002", "k_id" : "ka2", "p_id" : "po2", "name" : "生駒", "age" : 37, "salary" : 250000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1a"), "k_id" : "ka2", "b_id" : "bu2", "name" : "企画課" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d23"), "e_id" : "emp003", "k_id" : "ka3", "p_id" : "po3", "name" : "嘉喜", "age" : 23, "salary" : 200000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1b"), "k_id" : "ka3", "b_id" : "bu3", "name" : "開発1課" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d24"), "e_id" : "emp004", "k_id" : "ka4", "p_id" : "po4", "name" : "与田", "age" : 33, "salary" : 100000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1c"), "k_id" : "ka4", "b_id" : "bu3", "name" : "開発2課" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d25"), "e_id" : "emp005", "k_id" : "ka3", "p_id" : "po4", "name" : "松田", "age" : 35, "salary" : 550000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1b"), "k_id" : "ka3", "b_id" : "bu3", "name" : "開発1課" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d26"), "e_id" : "emp006", "k_id" : "ka4", "p_id" : "po4", "name" : "菅井", "age" : 45, "salary" : 120000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1c"), "k_id" : "ka4", "b_id" : "bu3", "name" : "開発2課" } ] }

“division_docs”という配列のデータが、結合したコレクションから取得したデータになります。

結合したコレクションの表示フィールドを絞る

$projectを使うと、結合したコレクションの表示フィールドを絞って表示することができます。

_idを非表示にして、従業員コレクションのnameと課コレクションのnameだけを表示してみます。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> db.employee.aggregate([
{$lookup:{
from: "division",
localField:"k_id",
foreignField:"k_id",
as: "division_docs"
}},
{$project:{
"_id":0,
"name":1,
"division_docs.name":1
}}
])
{ "name" : "高山", "division_docs" : [ { "name" : "総務課" } ] }
{ "name" : "生駒", "division_docs" : [ { "name" : "企画課" } ] }
{ "name" : "嘉喜", "division_docs" : [ { "name" : "開発1課" } ] }
{ "name" : "与田", "division_docs" : [ { "name" : "開発2課" } ] }
{ "name" : "松田", "division_docs" : [ { "name" : "開発1課" } ] }
{ "name" : "菅井", "division_docs" : [ { "name" : "開発2課" } ] }

指定した通りのフィールドを表示することができました。

Pythonで操作

上記の集計処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import pymongo
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# コレクションの結合
docs = db1.employee.aggregate([
{'$lookup':{
'from': 'division',
'localField':'k_id',
'foreignField':'k_id',
'as': 'division_docs'
}}
])
for doc in docs:
print(doc)

# 結合したコレクションの表示フィールドを絞る
docs = db1.employee.aggregate([
{'$lookup':{
'from': 'division',
'localField':'k_id',
'foreignField':'k_id',
'as': 'division_docs'
}},
{'$project':{
'_id':0,
'name':1,
'division_docs.name':1
}}
])
for doc in docs:
print(doc)

次回は、結合したコレクションをオブジェクト型と文字列型に展開します。