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

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中的文档会全部会留下来。

  1.  
    //集合A与集合B进行连接
  2.  
    for(docA in A){
  3.  
    dfs_join(docA.startWith, B, 0); //初始时使用startWith作为第一个值
  4.  
    }
  5.  
    //深度优先搜索
  6.  
    void dfs_join(docConnectFromField, B, deep){
  7.  
    if(deep > maxDeep){ //超过最大深度就退出
  8.  
    return;
  9.  
    }
  10.  
    for(docB in B){ //对B中的每个文档的connectToField与输入的docConnectFromField比较
  11.  
    if(docConnectFromField == docB.connectToField){
  12.  
    as.insert(docB); //匹配成功,保存dockB到as指定的数组里
  13.  
    dfs_join(docB.connectFromField, B, deep+1); //拿出docB的connectFromField继续进行匹配
  14.  
    }
  15.  
    }
  16.  
    }
  1.  
    {
  2.  
    $graphLookup: {
  3.  
    from: <collection>,
  4.  
    startWith: <expression>,
  5.  
    connectFromField: <string>,
  6.  
    connectToField: <string>,
  7.  
    as: <string>,
  8.  
    maxDepth: <number>,
  9.  
    depthField: <string>,
  10.  
    restrictSearchWithMatch: <document>
  11.  
    }
  12.  
    }
  1.  
    //查入数据
  2.  
    db.mp.insertMany([
  3.  
    {"val":1, "name":"A", "tar":["B","C"]},
  4.  
    {"val":2, "name":"B", "tar":["D","E"]},
  5.  
    {"val":3, "name":"C", "tar":["E","F"]},
  6.  
    {"val":4, "name":"D", "tar":["F","A"]}
  7.  
    ])
  8.  
     
  9.  
    db.src.insertMany([
  10.  
    {"uname":"A", "age":28, "addr":"shenzheng"},
  11.  
    {"uname":"B", "age":30, "addr":"hangzhou"}
  12.  
    ])
  13.  
     
  14.  
    //startWith是src.uname==mp.name(connectToField), 匹配成功后,取mp.tar(connectFromField)再与mp中的每个文档的name(connectToField)进行匹配,匹配成功后,取mptar....
  15.  
    //聚合
  16.  
    db.src.aggregate([
  17.  
    {
  18.  
    "$match":{
  19.  
    "age":{
  20.  
    "$gte":20
  21.  
    },
  22.  
    "uname":{
  23.  
    "$exists":1
  24.  
    }
  25.  
    }
  26.  
    },{
  27.  
    "$graphLookup":{
  28.  
    "from":"mp",
  29.  
    "startWith":"$uname",
  30.  
    "connectFromField":"tar", //这里tar是个数组,那么就用每个元素分别进行匹配
  31.  
    "connectToField":"name",
  32.  
    "as":"next",
  33.  
    "maxDepth":10
  34.  
    }
  35.  
    },
  36.  
    {
  37.  
    "$project":{
  38.  
    "_id":0,
  39.  
    "uname":1,
  40.  
    "next.name":1,
  41.  
    "next.tar":1
  42.  
    }
  43.  
    }
  44.  
    ])
  45.  
    //查询结果
  46.  
    { "uname" : "A", "next" : [ { "name" : "B", "tar" : [ "D", "E" ] }, { "name" : "C", "tar" : [ "E", "F" ] }, { "name" : "A", "tar" : [ "B", "C" ] }, { "name" : "D", "tar" : [ "F", "A" ] } ] }
  47.  
    { "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构成如下图。 

posted @ 2020-09-22 18:05  吃饭了吗  阅读(697)  评论(0编辑  收藏  举报