今回は、結合したコレクションをオブジェクト型と文字列型に展開します。
サンプルデータ
以前用意した会社の部、課、従業員データを使用します。
集計処理(aggregate)①データ準備 - https://ailog.site/2021/09/02/2021/0902/
オブジェクト型に変換
前回のコレクション結合では、結合先コレクションのdivision_docsが [{}] というように配列の中にオブジェクトが入っている構造になっています。
$unwindを使うと、配列の中の値を展開することができます。
[Mongoシェル]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| > db.employee.aggregate([ {$lookup:{ from: "division", localField:"k_id", foreignField:"k_id", as: "division_docs" }}, {$project:{ "_id":0, "name":1, "division_docs.name":1 }}, {$unwind:"$division_docs"} ]) { "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課" } }
|
division_docsの[]がとれて、{}というオブジェクト型になりました。
文字列型に変換
次にオブジェクト型を文字列型に変換します。
オブジェクト型に変換したデータに対して$groupを使い_id(集計キー)にe_id(従業員ID)を指定します。
e_idはユニークなので集計されません。
さらに表示したいフィールドに何らかの集計関数(maxなど)を使って、オブジェクト型から文字列型に変換します。
[Mongoシェル]
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
| > db.employee.aggregate([ {$lookup:{ from: "division", localField:"k_id", foreignField:"k_id", as: "division_docs" }}, {$project:{ "_id":0, "e_id":1, "name":1, "division_docs.name":1 }}, {$unwind:"$division_docs"}, {$group:{ _id:"$e_id", employeeName:{$max:"$name"}, divisionName:{$max:"$division_docs.name"} }} ]) { "_id" : "emp002", "employeeName" : "生駒", "divisionName" : "企画課" } { "_id" : "emp001", "employeeName" : "高山", "divisionName" : "総務課" } { "_id" : "emp004", "employeeName" : "与田", "divisionName" : "開発2課" } { "_id" : "emp006", "employeeName" : "菅井", "divisionName" : "開発2課" } { "_id" : "emp005", "employeeName" : "松田", "divisionName" : "開発1課" } { "_id" : "emp003", "employeeName" : "嘉喜", "divisionName" : "開発1課" }
|
結合した課コレクションの課の名称(division_docs.name)を、オブジェクト型から文字列型に変換することができました。
少々強引な方法なので、アプリケーション側で処理した方が楽に展開できるかもしれません。
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 38 39 40 41 42 43 44 45 46 47 48 49 50
| import pymongo from pymongo import MongoClient
client = MongoClient()
db1 = client.db1
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 }}, {'$unwind':'$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, 'e_id':1, 'name':1, 'division_docs.name':1 }}, {'$unwind':'$division_docs'}, {'$group':{ '_id':'$e_id', 'employeeName':{'$max':'$name'}, 'divisionName':{'$max':'$division_docs.name'} }} ]) for doc in docs: print(doc)
|
次回は、コレクションの二重結合を行います。