mongodb之图聚合查询 之图查询$graphLookup

mongodb之图聚合查询 之图查询$graphLookup

官网的流程解释:

$graphLookup

Performs a recursive search on a collection, with options for restricting the search by recursion depth and query filter.

The $graphLookup search process is summarized below:

  1. Input documents flow into the $graphLookup stage of an aggregation operation.

  2. $graphLookup targets the search to the collection designated by the from parameter (see below for full list of search parameters).

  3. For each input document, the search begins with the value designated by startWith. 对每个输入的文档,先用startWith来匹配。

  4. $graphLookup matches the startWith value against the field designated by connectToField in other documents in the from collection. startWith来匹配from文档里的connectToField。只是第一轮。后边就不用startWith了

  5. For each matching document, $graphLookup takes the value of the connectFromField and checks every document in the from collection for a matching connectToField value. For each match, $graphLookup adds the matching document in the from collection to an array field named by the as parameter.当startWith与from中的文档的connectToField匹配成功,就取connectFromField进行下一轮from里的connectToField进行匹配,一直递归循环,直到最大深度。

    This step continues recursively until no more matching documents are found, or until the operation reaches a recursion depth specified by the maxDepth parameter. $graphLookup then appends the array field to the input document. $graphLookup returns results after completing its search on all input documents. 设置最大递归层次。

综上进行如下流程:A join B join B join B join ...    其中A,B都是集合。是左外连接。也就是A中的文档会全部会留下来。

//集合A与集合B进行连接
for(docA in A){
    dfs_join(docA.startWith, B, 0); //初始时使用startWith作为第一个值
}
//深度优先搜索
void dfs_join(docConnectFromField, B, deep){
     if(deep > maxDeep){    //超过最大深度就退出
         return;
     }
     for(docB in B){   //对B中的每个文档的connectToField与输入的docConnectFromField比较
        if(docConnectFromField == docB.connectToField){
            as.insert(docB); //匹配成功,保存dockB到as指定的数组里
            dfs_join(docB.connectFromField, B, deep+1); //拿出docB的connectFromField继续进行匹配
        }
     }
}
{
   $graphLookup: {
      from: <collection>,
      startWith: <expression>,
      connectFromField: <string>,
      connectToField: <string>,
      as: <string>,
      maxDepth: <number>,
      depthField: <string>,
      restrictSearchWithMatch: <document>
   }
}
//查入数据
db.mp.insertMany([ 
{"val":1, "name":"A", "tar":["B","C"]},
{"val":2, "name":"B", "tar":["D","E"]},
{"val":3, "name":"C", "tar":["E","F"]},
{"val":4, "name":"D", "tar":["F","A"]}
])

db.src.insertMany([
{"uname":"A", "age":28, "addr":"shenzheng"},
{"uname":"B", "age":30, "addr":"hangzhou"}
])

//startWith是src.uname==mp.name(connectToField), 匹配成功后,取mp.tar(connectFromField)再与mp中的每个文档的name(connectToField)进行匹配,匹配成功后,取mptar....
//聚合
db.src.aggregate([
{
    "$match":{
        "age":{
            "$gte":20
         },
        "uname":{
            "$exists":1
        }
    }
},{
    "$graphLookup":{
        "from":"mp",
        "startWith":"$uname",
        "connectFromField":"tar", //这里tar是个数组,那么就用每个元素分别进行匹配
        "connectToField":"name",
        "as":"next",
        "maxDepth":10
    }
},
{
    "$project":{
        "_id":0,
        "uname":1,
        "next.name":1,
        "next.tar":1
    }
}
])
//查询结果
{ "uname" : "A", "next" : [ { "name" : "B", "tar" : [ "D", "E" ] }, { "name" : "C", "tar" : [ "E", "F" ] }, { "name" : "A", "tar" : [ "B", "C" ] }, { "name" : "D", "tar" : [ "F", "A" ] } ] }
{ "uname" : "B", "next" : [ { "name" : "B", "tar" : [ "D", "E" ] }, { "name" : "C", "tar" : [ "E", "F" ] }, { "name" : "A", "tar" : [ "B", "C" ] }, { "name" : "D", "tar" : [ "F", "A" ] } ] }

注意,as(next)里的数据是没顺序的。最后uname=A的next构成如下图。 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值