查詢類報表mongodb語句設計
阿新 • • 發佈:2019-01-31
1. 需求分析
表單分A、B兩張表單。Afield1、Bfield1為兩張表的關聯欄位;Afield2、Bfield2為需要查詢的欄位。
兩張表的資料都儲存在test表中。
2. 測試資料
{
"_id" : ObjectId("59ddb60c008ad60934c5194d"),
"A-field1" : 1,
"A-field2" : 2,
"formid" : "A"
}
{
"_id" : ObjectId("59ddb658008ad60934c5194f"),
"B-field1" : 1,
"B-field2" : 2,
"formid" : "B"
}
{
"_id" : ObjectId("59ddb9da008ad60934c51952"),
"A-field1" : 2,
"A-field2" : 2,
"formid" : "A"
}
{
"_id" : ObjectId("59ddbcc1008ad60934c51955"),
"A-field1" : 1,
"A-field2" : 4,
"formid" : "A"
}
3. 查詢語句
使用聚合進行查詢,第一版sql
db.test.aggregate([
{
// 我們指定查詢我們需要的欄位,即關聯欄位和查詢的欄位
// 我們要根據關聯的欄位為每條資料生成一個分組的key,我們就可以通過分組把資料關聯起來,分組key的邏輯:如果A-field1欄位存在,則key值為A-field1欄位的值,B-field1欄位存在,則key值為B-field1欄位的值,因為兩個欄位分屬不同的表單,所以不會同時存在一條資料上,所以需要用到ifNull來判斷
"$project" :{
"Afield1": "$A-field1",
"Afield2": "$A-field2",
"Bfield1": "$B-field1",
"Bfield2": "$B-field2",
"formid" : 1,
"groupkey":{
$ifNull: [ "$A-field1", {
$ifNull: [ "$B-field1" , null ]
} ]
}
}
},{
// 我們根據分組欄位,把能相互關聯的欄位進行分組查詢, fieldA為A表的資料,fieldB為B表的資料
"$group" :{
_id : { "groupkey" : "$groupkey" },
"fieldA" : {$push: { Afield2 : "$Afield2" } },
"fieldB" : {$push: { Bfield2 : "$Bfield2" } }
}
},
{
// 我們把陣列為空的資料過濾掉
$project: {
_id : 1,
fieldA: {
$filter: {
input: "$fieldA",
as: "fieldA",
cond: { $ne: [ "$$fieldA", {} ] }
}
},
fieldB: {
$filter: {
input: "$fieldB",
as: "fieldB",
cond: { $ne: [ "$$fieldB", {} ] }
}
}
}
},{
// 查詢資料後我們要橫向拆分資料,我們得計算出一組資料中會生成多少行資料,為什麼要做這件事,因為... 不這麼幹沒法做翻頁
$project:{
_id : 1,
fieldA : 1,
fieldB : 1,
rowCount : { $cond: { if: { $gte: [ { $size: "$fieldA" }, { $size: "$fieldB" } ] }, then: { $size: "$fieldA" }, else: { $size: "$fieldB" } }}
}
},{
// 然後把行數拆分成索引
$project:{
_id : 1,
fieldA : 1,
fieldB : 1,
rowCount : { $range: [ 0, "$rowCount" ] }
}
},{
// 根據索引拼表格資料
$project : {
data : {
$map:
{
input: "$rowCount",
as: "index",
in: { A :{ $arrayElemAt: [ "$fieldA", "$$index" ] }, B: { $arrayElemAt: [ "$fieldB", "$$index" ] }}
}
}
}
},
// 然後進行陣列拆分,完成資料
{ $unwind : "$data" }
// 最後進行分頁即可
]);
優化語句