溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

玩轉Mongo計算

發布時間:2020-08-09 05:48:37 來源:網絡 閱讀:511 作者:raqsoft 欄目:大數據

MongoDB屬于 NoSql 中的基于分布式文件存儲的文檔型數據庫,是非關系數據庫當中功能最豐富,最像關系數據庫的。它支持的數據結構非常松散,是類似 json 的 bson 格式,因此可以存儲比較復雜的數據類型。Mongo 最大的特點是它支持的查詢語言非常強大,其語法有點類似于面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,但是寫起來并不簡單。若能集算器 SPL 語言結合,處理起來就相對容易多了。

        現在我們針對 MongoDB 在計算方面的問題進行討論分析,通過集算器 SPL 語言加以改進,方便用戶使用 MongoDB?,F從如下情況加以說明:

1. 單表內嵌數組結構的統計............................................... 1
2. 單表內嵌文檔求和......................................................... 3
3. 分段分組結構................................................................ 5
4. 同構表合并................................................................... 6
5. 關聯嵌套結構情況 1...................................................... 8
6. 關聯嵌套結構情況 2..................................................... 10
7. 關聯嵌套結構情況 3..................................................... 11
8. 多字段分組統計........................................................... 14
9. 兩表關聯查詢............................................................... 16
10. 多表關聯查詢............................................................. 17
11. 指定數組查找............................................................. 19
12. 關聯表中的數組查找................................................... 20
 

1. 單表內嵌數組結構的統計

對嵌套數組結構中的數據統計處理。查詢考試科目的平均分及每個學生的總成績情況。
測試數據:

_idnamesexScroe
1TomF[{"lesson":" Physics      ","mark":60   },
  {"lesson":" Chemical      ","mark":72 }]    
2JerryM[{"lesson":" Physics      ","mark":92   },
  {"lesson":" Math      ","mark":81 }]    

期待統計結果:

Physics76
Tom132
Chemical72
Jerry173
Math81


腳本:

db.student.aggregate( [
  {$unwind : "$scroe"},
{$group: {
  "_id":   {"lesson":"$scroe.lesson"} ,
  "qty":{"$avg":   "$scroe.mark"}
  }
}
] )

db.student.aggregate( [
  {$unwind : "$scroe"},
{$group: {
  "_id": {"name"   :"$name"} ,
  "qty":{"$sum" :   "$scroe.mark"}
  }
}
 ] )

由于各科分數 scroe 是按課目、成績記錄的數組結構,統計前需要將它拆解,將每科成績與學生對應,然后再實現分組計算。這需要熟悉 unwind 與 group 組合的應用。

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"student.find()").fetch()
3=A2.conj(scroe).groups(lesson:LESSON;avg(mark):AVG)
4=A2.new(name:NAME,scroe.sum(mark):TOTAL)
5>A1.close()

按課目統計的總分數

LESSONAVG
Chemical72.0
Math81.0
Physics76.0

每個學生的總成績

NAMETOTAL
Tom132
Jerry173

腳本說明:
      A1:連接 mongo 數據庫。
      A2:獲取 student 表中的數據。
      A3:將 scroe 數據合并成序表,再按課程分組,計算平均分。
      A4:統計每個學生的成績后返回列名為 NAME、TOTAL 的序表。new 函數表示生成新序表。
      A5:關閉數據庫連接。
 
這個比較常用嵌套結構統計的例子許多人遭遇過、需要先拆解,主要是熟悉 mongodb 對嵌套數據結構的處理。

2. 單表內嵌文檔求和

對內嵌文檔中的數據求和處理, 下面要統計每條記錄的 income,output 的數量和。
測試數據:

_idincomeoutput
1{"cpu":1000, "mem":500,   "mouse":"100"}{"cpu":1000, "mem":600 ,"mouse":"120"}
2{"cpu":2000, "mem":1000,
  "mouse":"50","mainboard":500 }
{"cpu":1500, "mem":300 }

期待統計結果

_idincomeoutput
116001720
235501800

Mongodb腳本:

var fields = [  "income", "output"];
db.computer.aggregate([ 
   { 
      $project:{ 
         "values":{ 
            $filter:{ 
               input:{ 
                    "$objectToArray":"$$ROOT"
               },
               cond:{ 
                  $in:[ 
                     "$$this.k",
                     fields
                  ]
               }
            }
         }
      }
   },
   { 
      $unwind:"$values"
   },
   { 
      $project:{ 
         key:"$values.k",
         values:{ 
            "$sum":{ 
               "$let":{ 
                  "vars":{ 
                     "item":{ 
                        "$objectToArray":"$values.v"
                     }
                  },
                    "in":"$$item.v"
               }
            }
         }
      }
   },
   {$sort: {"_id":-1}},
   { "$group": {
    "_id": "$_id",
    'income':{"$first":   "$values"},
    "output":{"$last":   "$values"}
    }},
]);

filter將income,output 部分信息存放到數組中,用 unwind 拆解成記錄,再累計各項值求和,按 _id 分組合并數據。

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"computer.find()").fetch()
3=A2.new(_id:ID,income.array().sum():INCOME,output.array().sum():OUTPUT)
4>A1.close()

統計結果

IDINCOMEOUTPUT
11600.01720.0
23550.01800.0

腳本說明:
      A1:連接數據庫
      A2:獲取 computer 表中的數據
      A3:將 income、output 字段中的數據分別轉換成序列求和,再與 ID 組合生成新序表
      A4:關閉數據庫連接。

獲取子記錄的字段值,然后求和,相對于 mongo 腳本簡化了不少。這個內嵌文檔與內嵌數組在組織結構上有點類似,不小心容易混淆,注意與上例中的 scroe 數組結構比較,寫出的腳本有所不同。

3. 分段分組結構

統計各段內的記錄數量。下面按銷售量分段,統計各段內的數據量,數據如下:

_idNAMESTATESALES
1AshleyNew York11000
2RachelMontana9000
3EmilyNew York8800
4MatthewTexas8000
5AlexisIllinois14000

分段方法:0-3000;3000-5000;5000-7500;7500-10000;10000 以上。

期望結果:

Segmentnumber
33
42

Mongo 腳本

var a_count=0;
var b_count=0;
var c_count=0;
var d_count=0;
var e_count=0;
db.sales.find({
   
}).forEach(
    function(myDoc) {
        if (myDoc.SALES <3000)   {
            a_count += 1;
        }
        else if (myDoc.SALES <5000)   {
            b_count += 1;
        }
        else if (myDoc.SALES   <7500) {
            c_count += 1;
        }
        else if (myDoc.SALES   <10000) {
            d_count += 1;
        }
        else {
            e_count += 1;
        }       
    }
    );
   
print("a_count="+a_count)
print("b_count="+b_count)
print("c_count="+c_count)
print("d_count="+d_count)
print("e_count="+e_count)

這個需求按條件分段分組,mongodb 沒有提供對應的 api,實現起來有點繁瑣,上面的程序是其中實現的一個例子參考,當然也可以寫成其它實現形式。下面看看集算器腳本的實現。

SPL  腳本:  


AB
1[3000,5000,7500,10000,15000]
2=mongo_open("mongodb://127.0.0.1:27017/raqdb")
3=mongo_shell(A2,"sales.find()").fetch()
4=A3.groups(A1.pseg(int(~.SALES)):Segment;count(1):   number)
5>A2.close()

腳本說明:
      A1:定義 SALES 分組區間。
      A2:連接 mongodb 數據庫。
      A3:獲取 sales 表中的數據。
      A4:根據 SALES 區間分組統計員工數。其中函數 pseg()表示返回成員在序列中的區段序號,int() 表示轉換成整數。
      A5:關閉數據庫連接。

pseg 的使用讓 SPL 腳本精簡了不少。

4. 同構表合并

具有相同結構的多表數據合并。下面將兩個員工表數據合并。
Emp1:  

_idNAMESTATEHIREDATEDEPTSALARY
1AshleyNew York2008-03-16Finance11000
2RachelMichigan2001-04-16Sales9000
3EmilyNew York2011-07-11HR8800
4MatthewTexas2003-03-06R&D8000
5AlexisIllinois2008-03-10Sale14000

Emp2:

_idNAMESTATEHIREDATEDEPTSALARY
10JacobNew York2009-03-14Sales13000
12JessicaFlorida2011-04-19Sales9500
13DanielNew York2001-02-11HR7800
14AlyssaMontana2013-09-06R&D8000
15HannahFlorida2015-06-10Sales12500

合并數據結果:

_idNAMESTATEHIREDATEDEPTSALARY
1AshleyNew York2008-03-16Finance11000
2RachelMichigan2001-04-16Sales9000
3EmilyNew York2011-07-11HR8800
4MatthewTexas2003-03-06R&D8000
5AlexisIllinois2008-03-10Sale14000
10JacobNew York2009-03-14Sales13000
12JessicaFlorida2011-04-19Sales9500
13DanielNew York2001-02-11HR7800
14AlyssaMontana2013-09-06R&D8000
15HannahFlorida2015-06-10Sales12500

Mongo 腳本:

db.emp1.aggregate([
  {  "$limit": 1},
  {   "$facet": {
      "collection1": [
        {"$limit": 1},
        { "$lookup": {
          "from": "emp1",
          "pipeline": [{"$match": {} }],
          "as": "collection1"
        }}
      ],
      "collection2": [
        {"$limit": 1},
        { "$lookup": {
          "from": "emp2",
          "pipeline": [{"$match": {} }],
          "as": "collection2"
        }}
    ]
  }},
  {   "$project": {
      "data": {
        "$concatArrays": [
          {"$arrayElemAt": ["$collection1.collection1", 0]   },
          {"$arrayElemAt": ["$collection2.collection2", 0]   },
        ]
    }
  }},
  {  "$unwind": "$data"},
  {  "$replaceRoot": { "newRoot": "$data"} }
])

通過 facet 將兩表數據先存入各自的數組中,然后 concatArrays 將數組合并,unwind 拆解子記錄后,并將它呈現在最外層。SPL 腳本實現則沒有那么多“花樣”。

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"emp1.find()").fetch()
3=mongo_shell(A1,"emp2.find()").fetch()
4=A2|A3
5>A1.close()

腳本說明:
      A1:連接 mongodb 數據庫。
      A2:獲取 emp1 表中的數據。
      A3:獲取 emp2 表中的數據。
      A4:合并兩表數據。
      A5:關閉數據庫連接。

熟悉 sql 語句的 mongo 初學者面對數據合并的 mongo 腳本,估計首次遇到時有點“懵”,SPL 腳本就顯得自然易懂了。

5. 關聯嵌套結構情況 1

兩個關聯表,表 A 與表 B 中的內嵌文檔信息關聯, 且返回的信息在內嵌文檔中。表 childsgroup 字段 childs 是嵌套數組結構,需要合并的信息 name 在其下。
 history:  

_ididHistorychild_id
1001today workedch001
2002Workingch004
3003now workingch009

childsgroup:

_idgroupidnamechilds
1g001group1{"id":"ch001","info":{"name":"a"}},{"id":"ch002","info":{"name":"b"}}
2g002group1{"id":"ch004","info":{"name":"c"}},{"id":"ch009","info":{"name":"d"}}

表History中的child_id與表childsgroup中的childs.id關聯,希望得到下面結果:
{
    “_id” : ObjectId(“5bab2ae8ab2f1bdb4f434bc3”),
    “id” : “001”,
    “history” : “today worked”,
    “child_id” : “ch001”,
    “childInfo” :
    {
         “name” : “a”
    }
   ………………
}

Mongo 腳本

db.history.aggregate([
    {$lookup: {
        from:   "childsgroup",
        let: {child_id:   "$child_id"},
        pipeline: [
            {$match: {   $expr: { $in: [ "$$child_id", "$childs.id"] } } },
            {$unwind:   "$childs"},
            {$match: {   $expr: { $eq: [ "$childs.id", "$$child_id"] } } },
            {$replaceRoot: {   newRoot: "$childs.info"} }
            ],
            as:   "childInfo"
        }},
  {"$unwind": "$childInfo"}
])

這個腳本用了幾個函數lookup、pipeline、match、unwind、replaceRoot處理,一般 mongodb 用戶不容易寫出這樣復雜腳本;那我們再看看 spl 腳本的實現:

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"history.find()").fetch()
3=mongo_shell(A1,"childsgroup.find()").fetch()
4=A3.conj(childs)
5=A2.join(child_id,A4:id,info.name:name)
6>A1.close()

關聯查詢結果:

_ididhistorychild_idname
1001today workedch001a
2002workingch004c
3003now workingch009d

腳本說明:
      A1:連接 mongodb 數據庫。
      A2:獲取 history 表 中的數據。
      A3:獲取 childsgroup 表 中的數據。
      A4:將 childsgroup 中的 childs 數據提取出來合并成序表。
      A5:表 history 中的 child_id 與表 childs 中的 id 關聯查詢,追加 name 字段, 返回序表。
      A6:關閉數據庫連接。


相對 mongodb 腳本寫法,SPL 腳本的難度降低了不少,省去了熟悉有關 mongo 函數的用法,如何去組合處理數據等,節約了不少時間。

6. 關聯嵌套結構情況 2

兩個關聯表,表 A 與表 B 中的內嵌文檔信息關聯, 將信息合并到內嵌文檔中。表 txtPost 字段 comment 是嵌套數組結構,需要把 comment_content 合并到其下。

txtComment:

_IDcomment_nocomment_content
1143test test
2140math

txtPost

_IDpost_noComment
148[{"comment_no"   : 143, "comment_group" : 1} ]
247[{"comment_no"   : 140, "comment_group" : 2},
  {"comment_no" : 143, "comment_group" : 3} ]

期望結果:

_IDpost_noComment
148[{"comment_no"   : 143, "comment_group" : 1,"comment_content" : "test test"} ]
247[{"comment_no"   : 140, "comment_group" : 2,"comment_content" : "math"},
  {"comment_no" : 143, "comment_group" : 3,"comment_content" :   "test test"} ]

Mongo 腳本

db.getCollection("txtPost").aggregate([
  {  "$unwind": "$comment"},
  {   "$lookup": {
      "from": "txtComment",
      "localField": "comment.comment_no",
      "foreignField": "comment_no",
      "as": "comment.comment_content"
  }},
  {  "$unwind": "$comment.comment_content"},
  {  "$addFields": { "comment.comment_content":   "$comment.comment_content.comment_content"}},
  {   "$group": {
      "_id": "$_id",
      'post_no':{"$first": "$post_no"},
      "comment": {"$push": "$comment"}
      }},
 
    ]).pretty()

表txtPost 按 comment 拆解成記錄,然后與表 txtComment 關聯查詢,將其結果放到數組中,再將數組拆解成記錄,將comment_content 值移到 comment 下,最后分組合并。

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"txtPost.find()").fetch()
3=mongo_shell(A1,"txtComment.find()").fetch()
4=A2.conj(comment.derive(A2.post_no:pno))
5=A4.join(comment_no,A3:comment_no,comment_content:Content)
6=A5.group(pno;~:comment)
7>A1.close()

腳本說明:
      A1:連接 mongodb 數據庫。
      A2:獲取 txtPost 表 中的數據。
      A3:獲取 txtComment 表 中的數據。
      A4:將序表 A2 下的 comment 與 post_no 組合成序表,其中 post_no 改名為 pno。
      A5:序表 A4 通過 comment_no 與序表 A3 關聯,追加字段 comment_content,將其改名為 Content。
      A6:按 pno 分組返回序表,~ 表示當前記錄。
      A7:關閉數據庫連接。

7. 關聯嵌套結構情況 3

兩個關聯表,表 A 與表 B 中的內嵌文檔信息關聯, 且返回的信息在記錄上。表 collection2 字段 product 是嵌套數組結構,返回的信息是 isCompleted 等字段。
 測試數據:  

collection1:
{
   _id: '5bc2e44a106342152cd83e97',
   description:
    {
      status: 'Good',
      machine: 'X'
     },
   order: 'A',
   lot: '1'
   };
  
collection2:
{
   _id: '5bc2e44a106342152cd83e80',
   isCompleted: false,
   serialNo: '1',
   batchNo: '2',
   product: [ // note the subdocuments here
        {order: 'A', lot: '1'},
        {order: 'A', lot: '2'}
    ]
}

期待結果
{
   _id: 5bc2e44a106342152cd83e97,
   description:
       {
         status: 'Good',
         machine: 'X',
       },
   order: 'A',
   lot: '1' ,
   isCompleted: false,
   serialNo: '1',
   batchNo: '2'
}

Mongo 腳本

db.collection1.aggregate([{
       $lookup:   {
              from:   "collection2",
              let:   {order: "$order", lot: "$lot"},
              pipeline:   [{
                     $match:   {
                     $expr:{  $in: [ { order: "$$order", lot: "$$lot"},   "$product"] }
                     }  
                     }],  
                     as:   "isCompleted"
                     }  
              },   {
                     $addFields:   {
                     "isCompleted":   {$arrayElemAt: [ "$isCompleted", 0] }
                     }  
              },   {
                     $addFields:   { // add the required fields to the top level structure
                     "isCompleted":   "$isCompleted.isCompleted",
                       "serialNo":   "$isCompleted.serialNo",
                     "batchNo":   "$isCompleted.batchNo"
              }  
}])

lookup 兩表關聯查詢,首個 addFields獲取isCompleted數組的第一個記錄,后一個addFields 轉換成所需要的幾個字段信息

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"collection1.find()").fetch()
3=mongo_shell(A1,"collection2.find()").fetch()
4=A3.conj(A2.select(order:A3.product.order,lot:A3.product.lot).derive(A3.serialNo:sno,A3.batchNo:bno))
5>A1.close()

腳本說明:
      A1:連接 mongodb 數據庫。
      A2:獲取 collection1 表 中的數據。
      A3:獲取 collection2 表 中的數據。
      A4:根據條件 order, lot 從序表 A2 中查詢記錄,然后追加序表 A3 中的字段 serialNo, batchNo,返回合并后的序表。
      A5:關閉數據庫連接。

實現從數據記錄中的內嵌結構中篩選,將符合條件的數據合并成新序表。

8. 多字段分組統計

統計分類項下的總數及各子項數。下面統計按 addr 分類 book 數及其下不同的 book 數。

addrbook
address1book1
address2book1
address1book5
address3book9
address2book5
address2book1
address1book1
address15book1
address4book3
address5book1
address7book11
address1book1

期望結果:

_idTotalbooksCount
address14book13


book51
address151book11
address23book12


book51
address31book91
address41book31
address51book11
address71book111

Mongo 腳本

db.books.aggregate([
    {   "$group": {
          "_id": {
              "addr": "$addr",
              "book": "$book"
        },
          "bookCount": {"$sum": 1}
    }},
    {   "$group": {
          "_id": "$_id.addr",
          "books": {
              "$push": {
                  "book": "$_id.book",
                  "count": "$bookCount"
            },
        },
          "count": {"$sum": "$bookCount"}
    }},
    {  "$sort": { "count": -1} },
    {   "$project": {
          "books": {"$slice": [ "$books", 2] },
          "count": 1
    }}
]).pretty()

先按 addr,book 分組統計 book 數,再按 addr 分組統計 book 數,調整顯示順序

SPL腳本:


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"books.find()")
3=A2.groups(addr,book;count(book):   Count)
4=A3.groups(addr;sum(Count):Total)
5=A3.join(addr,A4:addr,Total)
6>A1.close()

計算結果:

AddressbookCountTotal
address1book134
address1book514
address15book111
address2book123
address2book513
address3book911
address4book311
address5book111
address7book1111

腳本說明:
      A1:連接 mongodb 數據庫。
      A2:獲取books表中的數據。
      A3:按 addr,book 分組統計 book 數,
      A4:再按 addr 分組統計 book 數。
      A5:將 A4 中的 Total 按 addr 關聯后合并到序表中。
      A6:關閉數據庫連接。

9. 兩表關聯查詢

從關聯表中選擇所需要的字段組合成新表。

Collection1:

user1user2income
120.56
130.26

collection2:

user1user2output
120.3
130.4
230.5

期望結果:

user1user2incomeoutput
120.560.3
130.260.4

Mongo 腳本

db.c1.aggregate([
    {   "$lookup": {
      "from": "c2",
          "localField": "user1",
          "foreignField": "user1",
          "as": "collection2_doc"
      }},
    {  "$unwind": "$collection2_doc"},
    {   "$redact": {
          "$cond": [
              {"$eq": [ "$user2",   "$collection2_doc.user2"] },
              "$$KEEP",
              "$$PRUNE"
          ]
      }},
    {   "$project": {
          "user1": 1,
          "user2": 1,
          "income": "$income",
          "output": "$collection2_doc. output"
      }}
      ]).pretty()

lookup 兩表進行關聯查詢,redact 對記錄根據條件進行遍歷處理,project 選擇要顯示的字段。

SPL腳本:


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"c1.find()").fetch()
3=mongo_shell(A1,"c2.find()").fetch()
4=A2.join(user1:user2,A3:user1:user2,output)
5>A1.close()

腳本說明:
      A1:連接 mongodb 數據庫。
      A2:獲取c1表中的數據。
      A3:獲取c2表中的數據。
      A4:兩表按字段 user1,user2 關聯,追加序表 A3 中的 output 字段,返回序表。
      A5:關閉數據庫連接。

通過 join 把兩個關聯表不同的字段合并成新表。

10. 多表關聯查詢

多于兩個表的關聯查詢,結合成一張大表。

Doc1:

_idfirstNamelastName
U001shubhamverma

Doc2:

_iduserIdaddressmob
2U001Gurgaon9876543200

Doc3:

_iduserIdfbURLstwitterURLs
3U001http://www.facebook.comhttp://www.twitter.com

合并后的結果:
{
    "_id" : ObjectId("5901a4c63541b7d5d3293766"),
    "firstName" : "shubham",
    "lastName" : "verma",
 
    "address" : {
        "address" : "Gurgaon"
    },
    "social" : {
        "fbURLs" : "http://www.facebook.com",
        "twitterURLs" : "http://www.twitter.com"
    }
}

Mongo 腳本

db.doc1.aggregate([
    {$match:   { _id: ObjectId("5901a4c63541b7d5d3293766") } },
    {
          $lookup:
        {
              from: "doc2",
              localField: "_id",
              foreignField: "userId",
              as: "address"
        }
    },
    {
          $unwind: "$address"
    },
    {
          $project: {
              "address._id": 0,
              "address.userId": 0,
              "address.mob": 0
        }
    },
    {
          $lookup:
        {
              from: "doc3",
              localField: "_id",
              foreignField: "userId",
              as: "social"
        }
    },
    {
          $unwind: "$social"
    },
 
  {  
    $project:   {     
             "social._id": 0,     
             "social.userId": 0
       }
 }
]).pretty();

由于 Mongodb 數據結構原因,寫法也多樣化,展示也各不相同。

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"doc1.find()").fetch()
3=mongo_shell(A1,"doc2.find()").fetch()
4=mongo_shell(A1,"doc3.find()").fetch()
5=A2.join(_id,A3:userId,address,mob)
6=A5.join(_id,A4:userId,fbURLs,twitterURLs)
7>A1.close()

此腳本與上面例子類似,只是多了一個關聯表,每次 join 就新增加字段,最后疊加構成一張大表。.

SPL 腳本的簡潔性、統一性就非常明顯。

11. 指定數組查找

從指定的數組中查找符合條件的記錄。所給的數組為:["Chemical", "Biology", "Math"]。

測試數據:

_idNameLesson
1jacker[English, Chemical,Math, Physics]
2tom[Chinese, Chemical,Math,   Biology]
3Mint[Chinese, History]

期望結果:

_idNameLesson
1Jacker[Chemical,Math]
2Tom[Chemical,Math,Biology]

Mongodb 腳本

var field = ["Chemical",   "Biology", "Math"]
db.student.aggregate([
  {   "$project": {
      "name":1,
      "lessons": {
        "$filter": {
          "input": "$lesson",
          "cond": {
            "$in": [
              "$$this",
              field
            ]
          }
        }
        },
      }},
    {  "$project":   {"name":1,"lessons":1,"sizeOflesson":   {"$size": "$lessons"} }},
    {  $match: { "sizeOflesson":{ $gt: 0}}}
])

查詢選修課包含["Chemical", "Biology", "Math"]的同學。

SPL  腳本:  


AB
1[Chemical,   Biology, Math]
2=mongo_open("mongodb://127.0.0.1:27017/raqdb")
3=mongo_shell(A2,"student.find()").fetch()
4=A3.select(lesson^A1!=[])
5=A4.new(name,   ~.lesson^A1)
6>A2.close()

腳本說明:
      A1:定義查詢條件科目數組。
      A2:連接 mongodb 數據庫。
      A3:獲取 student 表中的數據。
      A4:查詢存在數組中的科目記錄。
      A5:生成字段為 name, lesson 的新序表,其中符合條件的值存放在字段 lesson 中
      A6:關閉數據庫連接。

集算器對給定數組中查詢記錄的實現更簡明易懂。

12. 關聯表中的數組查找

從關聯表記錄數據組中查找符合條件的記錄, 用給定的字段組合成新表。

測試數據:  

users:

_idNameworkouts
1000xxx[2,4,6]
1002yyy[1,3,5]

workouts:

_idDateBook
11/1/2001Othello
22/2/2001A   Midsummer Night's Dream
33/3/2001The Old   Man and the Sea
44/4/2001GULLIVER’S   TRAVELS
55/5/2001Pickwick   Papers
66/6/2001The Red   and the Black

期望結果:

Name_idDateBook
xxx22/2/2001A   Midsummer Night's Dream
xxx44/4/2001GULLIVER’S   TRAVELS
xxx66/6/2001The Red   and the Black
yyy11/1/2001Othello
yyy33/3/2001The Old   Man and the Sea
yyy55/5/2001Pickwick   Papers

Mongo 腳本

db.users.aggregate([
  { "$lookup": {
    "from" :   "workouts",
    "localField" :   "workouts",
    "foreignField" :   "_id",
    "as" :   "workoutDocumentsArray"
  }},
  {$project: {   _id:0,workouts:0} } ,
  {"$unwind":   "$workoutDocumentsArray"},;
  {"$replaceRoot": {   "newRoot":  { $mergeObjects:   [ "$$ROOT", "$workoutDocumentsArray"] } } },
  {$project: {   workoutDocumentsArray: 0} }
  ]).pretty()

把關聯表 users,workouts 查詢結果放到數組中,再將數組拆解,提升子記錄的位置,去掉不需要的字段。

SPL  腳本:  


AB
1=mongo_open("mongodb://127.0.0.1:27017/raqdb")
2=mongo_shell(A1,"users.find()").fetch()
3=mongo_shell(A1,"workouts.find()").fetch()
4=A2.conj(A3.select(A2.workouts^~.array(_id)!=[]).derive(A2.name))
5>A1.close()

腳本說明:
       A1:連接 mongodb 數據庫。
       A2:獲取 users 表中的數據。
       A3:獲取 workouts 表中的數據。
       A4:查詢序表 A3 的 _id 值存在于序表 A2 中 workouts 數組的記錄, 并追加 name 字段, 返回合并的序表。
       A5:關閉數據庫連接。

由于需要獲取序列的交集不為空為條件,故將 _id 轉換成序列。

        Mongo 存儲的數據結構相對關聯數據庫更復雜、更靈活,其提供的查詢語言也非常強、能適應不同的情況,需要了解函數也不少,函數之間的結合更是變化無窮,因此要掌握并熟悉應用它并非易事。集算器的離散性、易用性恰好能彌補 Mongo 這方面的不足,它降低了 mongo 學習成本及使用 mongo 操作的復雜度、難度,讓 mongo 的功能得到更充分的展現,同時也希望 mongo 越來越受到廣大愛好者的青睞。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女