日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MongoDB查询实现 笛卡尔积,Union All 和Union 功能

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MongoDB查询实现 笛卡尔积,Union All 和Union 功能 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自? ?MongoDB查詢實現 笛卡爾積,Union All 和Union 功能

此篇文章及以后的文章大部分都是從聚合管道(aggregation pipeline)的一些語法為基礎講解的,如果不理解聚合管道的話,可以先學習一下會比較容易理解.
可以參考 mongoDB Documentation 的?Pipeline Aggregaion Stages.

何為Union All 和 Union

Union All指令的目的是將兩個結果放在一起并且不管是否有重復,Union指令則把結果合并且去掉重復結果.


SQL中的實現Union All

在sql中,我們可以很簡單的就實現 Union All 的效果.比如在sql中,我們的數據是

tableAidtypetableBidtype
?1OPEN?1OPEN
?2CLOSE?2ISSUE
?3REJECT?3VOID
?4REQUEST???

我們在sql中 Union All 的寫法是:

select?a.type?as?type?from?tableA?a?Union?All?select?b.type?from?tableB?b;

得到的結果是:

type
OPEN
CLOSE
REJECT
REQUEST
OPEN
ISSUE
VOID

MongoDB 的語法實現

在MongoDB中,對于給我們表聯結相關使用的函數,有aggregate中的$lookup函數,
參照我們的官方例子,我們很容易就能理解$lookup函數的作用,相當于我們在sql里面的表聯結,如:

select?a.*,b.*?from?tableA?a,tableB?as?b?where?a._id?=?b.tableAId;

$lookup函數中,有以下參數為必填:

  • from: <collection to join>,?//等價于上面的 tableB

  • localField: <field from the input documents>,??// ?等價于上面的 a._id

  • foreignField: <field from the documents of the "from" collection>,?//等價于上面的 b.tableAId

  • as: <output array field>?// 等價于上面as后面的 b

那么如何使用聯結作用的函數來實現Union All 的作用呢?其實很簡單,在上面的4個參數里面,localField?和?foreignField?是必填的,但是在mongo里面,我們可以填寫一個無效的field(不存在表里面的field)來實現我們的效果

我們的測試數據如下:

tableA {"_id":"1","type":"OPEN"} {"_id":"2","type":"CLOSE"} {"_id":"3","type":"REJECT"} {"_id":"4","type":"REQUECT"} tableB {"_id":"1","type":"OPEN"} {"_id":"2","type":"ISSUE"} {"_id":"3","type":"VOID"}

1. 實現笛卡爾積

首先我們寫的查詢語句如下,將localField?和?foreignField隨便填寫一個String語句,只要是不在表里面存在的field即可

db.tableA.aggregate([{$lookup:{from:"tableB",localField:"invalidField",foreignField:"testField",as:"tableB"}} ])

查詢結果:

_idtypetableB
1OPEN[3 elements]
1CLOSE[3 elements]
1REJECT[3 elements]
1REQUEST[3 elements]

在MongoDB里面,field的判斷是空等于空的,value的判斷空是不等于空的. 兩個等于空的field去比較,相當于 在sql 里面 where 1=1 的寫法.

可以看到,我們tableA的每一條記錄都匹配到了tableB的3個元素(所有數據),此時只要我們將tableB的記錄?$unwind出來,就實現了笛卡爾積的效果了.

$unwind語法如下:

db.tableA.aggregate([{$lookup:{from:"tableB",localField:"invalidField",foreignField:"testField",as:"tableB"}},{$unwind:{path:"$tableB"}},{$project:{_id:1,type:1,tableBId:"$tableB._id",tableBType:"$tableB.type"}} ])

等價于sql語句:

select?a.id,a.type,b.id?as?tableId,b.type?as?tableBType?from?tableA?a,tableB?bwhere?1=1;

查詢結果可以自行測試


2. 實現Union

在MongoDB里面,有一個$setUnion的函數,$setUnion函數被union的參數必需是數組,
在我們tableA lookup tableB之后返回來的結果,tableB已經是一個一個數組了,但是我們的tableA的type是一個字符串值,所以我們需要先將tableA的內容先轉為數組,才能進行union.

All operands of $setUnion must be arrays.

將tableA里面的所有記錄轉為一個數組需要用到$gourp函數里面的$push功能.
查詢語法如下:

db.tableA.aggregate([{$group:{_id:"any",tableA:{$push:?"$$ROOT"}}} ])

查詢結果:

_idtableA
any[4 elements]

因為$gourp函數里面的_id屬性是必選的,但是這里我們不用到,所以填任意字符串或者null都可以.使用$push之后,tableA的所有記錄,都被push到了我們命名為tableA的數組里面,
此時我們在$lookup?tableB看看結果如何.
查詢語法如下:

db.tableA.aggregate([{$group:{_id:"any",typeArray:{$push:?"$$ROOT"}}},{$lookup:{from:"tableB",localField:"invalidField",foreignField:"testField",as:"tableB"}}? ])

查詢結果:

_idtableAtableB
any[4 elements][3 elements]

可以看到,我們的tableA,和tableB的結果都變成了數組,此時我們已經可以使用$setUnion函數去實現我們的Union效果了

db.tableA.aggregate([{$group:{_id:"any",tableA:{$push:?"$$ROOT"}}},{$lookup:{from:"tableB",localField:"invalidField",foreignField:"testField",as:"tableB"}},{$project:{_id:0,allValue:{$setUnion:["$tableA","$tableB"]}}} ])

查詢結果:

allValue
[6 elements]

此處只有6個元素在數組里面,已經把重復的去掉了,可以說我們的Union效果已經實現,之后在把結果用$unwind展開即可.
查詢語法如下:

db.tableA.aggregate([{$group:{_id:"any",tableA:{$push:?"$$ROOT"}}},{$lookup:{from:"tableB",localField:"invalidField",foreignField:"testField",as:"tableB"}},{$project:{_id:0,allValue:{$setUnion:["$tableA","$tableB"]}}},{$unwind:{path:"$allValue"}},{$project:{_id:0,type:"$allValue.type"}},])

3. 實現Union All

實現Union All 的原理與union 的類似,我們可以在把tableA push 成一個數組前,新增一個field,或者只push type,那么在union的時候,因為table A 和 table B field 數量不一致,那么永遠不會合并成一行,因為它們任意一行都是不一樣的.
查詢語法如下:

db.tableA.aggregate([{$group:{_id:"any",tableA:{$push:?{type:"$type"}}}},{$lookup:{from:"tableB",localField:"invalidField",foreignField:"testField",as:"tableB"}},{$project:{_id:0,allValue:{$setUnion:["$tableA","$tableB"]}}},{$unwind:"$allValue"},{$project:{_id:0,type:"$allValue.type"}} ])

Union All 的結果,可以通過group的方式去重來變成 Union 的效果.?$group函數在此就不再細講,可以參考官網.


總結

在我們的MongoDB官方文檔里面介紹了一些函數的基本語法,但是功能方面比較Oracle等傳統關系型數據庫來說還是比較少的,因為一些如本文講的Union等這些功能,只能根據現有的功能去實現.
而在官網和網上現有的資料里面,是沒有實現Union這些功能的介紹的,因此寫下了這篇文檔.

?

總結

以上是生活随笔為你收集整理的MongoDB查询实现 笛卡尔积,Union All 和Union 功能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。