官网的流程解释:

$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构成如下图。 

public void getByLikeUserId(PublishDto publishDto) { LookupOperation lookupOperation = LookupOperation.newLookup() .from("like") .localField("userId") .foreignField("userId") .as(... 虽说现在关系型数据库还是主流,但是面对某些需求的时候,需要非关系型数据库来补充它,学习一个主流的NoSQL数据库还是很有必要的。MongoDB是一个功能丰富的NoSQL数据库,本文整理了它最常用的部分形成了这篇入门教程,希望对大家有所帮助。 MongoDB是一个基于分布式文件存储的数据库。由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库当中功能最丰富,最像关系型数据库的。 以前写的. 由于之前用mongodb写程序刚开始老是Documnet很烦后来网上找了写自己总结了一下啊 Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(Criteria.where("PID").is("2021011408")), Aggregation.group("QLEVEL","STCD").count().as("cou MONGODB 已经走到了6.0,但大多数的公司使用MONGODB 可能都没有到5.0 这个版本,大多还在4.X晃悠,偶然看到一篇关于 7大理由升级到6.0的文字,翻译并分享,看看有什么需求促使我们升级到更高版本的MONGODB原文:https://www.mongodb.com/blog/post/big-reasons-upgrade-mongodb-6-0———————————————... 本篇文章探讨了大数据技术之MongoDB存储泛型List集合,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。protected virtual MongoConfigurationBuilder GetConfiguration(){var builder = new MongoConfigurationBuilder();builder.ReadConnectionStri... MongoDB Aggregation 聚合框架 文章目录MongoDB Aggregation 聚合框架前言1.MongoDB 聚合框架是什么2.管道(Pipeline)和步骤(Stage)3.聚合运算的基本格式4.步骤5.步骤中的运算符5.1 $match5.2 $project5.3 $group6.MQL & SQL 对比6.1 例16.2 例27.特殊步骤7.1 $unwind7.2 $bucket7.3 $facet8.MongoDB Compass(推荐工具)8.1 基本使用8.2 导   这篇我们来看mongodb另一个非常有意思的东西,那就是$lookup,我们知道mongodb是一个文档型的数据库,而且它也是最像关系型数据库的 一种nosql,但是呢,既然mongodb是无模式的,自然就很难在关系型数据库中非常擅长的多表关联上发挥作用,在这之前,我们可以使用DbRef,但 是呢,在mongodb 3.2 中给你增加了一个相当牛逼的手段,那就是$lookup,而且放到了a...