Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用带有条件的$graphLookup

使用带有条件的$graphLookup
EN

Stack Overflow用户
提问于 2018-06-14 06:05:24
回答 1查看 7.6K关注 0票数 6

我正试图找到一个孩子的祖先。在某种程度上,那个孩子的祖先的姓氏发生了变化。我想找到这个孩子最后一个姓的家长。例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "_id":1,
    "parent":null
    "first":"Bob",
    "last":"Sagget"
},
{
    "_id":2,
    "parent":1,
    "first":"Jane",
    "last":"Dor"
},
{
    "_id":3,
    "parent":2,
    "first":"Crane",
    "last":"Dor"
},
{
    "_id":4,
    "parent":3,
    "first":"Ho",
    "last":"Dor"
},
{
    "_id":5,
    "parent":4,
    "first":"Mor",
    "last":"Dor"
}

我想查询_id 5并获得姓Dor的祖先。在这个数据库中会有其他人的名字Dor,我不想看到,所以我不能只是查询姓氏"Dor“。

下面是我当前的聚合查询--这给了我所有的祖先,直到1的_id。我如何在2的_id停止呢?:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db.PeopleDb.aggregate(
[
    {
        $graphLookup: {
                "from": "PeopleDb", 
                "startWith": "$parent", 
                "connectFromField": "parent", 
                "connectToField": "_id", 
                "as": "linearAncestors"
            }
        },
        {
        $match: {
        "_id":5
        }
    },
]);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-14 17:39:07

相反,您要查找的基本查询实际上“开始”时限制只将单数文档与_id: 5匹配,然后执行$graphLookup以查找祖先。

至于“条件”,需要采取一些步骤,所以最好是贯穿整个过程,了解正在发生的事情:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db.PeopleDb.aggregate([
  { "$match": { "_id": 5 } },
  { "$graphLookup": {
    "from": "PeopleDb",
    "startWith": "$parent",
    "connectFromField": "parent",
    "connectToField": "_id",
    "as": "people",
    "depthField": "depth"
  }}
])

然后返回连接parent_id的所有递归链,并注意到“可选”"depthField"设置,以在返回的结果中包含匹配的实际“深度”:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "_id" : 5,
    "parent" : 4,
    "first" : "Mor",
    "last" : "Dor",
    "people" : [
        {
            "_id" : 1,
            "parent" : null,
            "first" : "Bob",
            "last" : "Sagget",
            "depth" : NumberLong(3)
        },
        {
            "_id" : 2,
            "parent" : 1,
            "first" : "Jane",
            "last" : "Dor",
            "depth" : NumberLong(2)
        },
        {
            "_id" : 3,
            "parent" : 2,
            "first" : "Crane",
            "last" : "Dor",
            "depth" : NumberLong(1)
        },
        {
            "_id" : 4,
            "parent" : 3,
            "first" : "Ho",
            "last" : "Dor",
            "depth" : NumberLong(0)
        }
    ]
}

因此,注意到4是返回的,因为它是初始文档的父文档,然后是它的父文档的3,然后是它的父文档的2,等等。

您可以使用“可选”"maxDepth"参数将匹配的“深度”限制在管道阶段,或者在“排除根”元素的特定情况下,可以使用"restrictSearchWithMatch"选项简单地排除null父元素的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db.PeopleDb.aggregate([
  { "$match": { "_id": 5 } },
  { "$graphLookup": {
    "from": "PeopleDb",
    "startWith": "$parent",
    "connectFromField": "parent",
    "connectToField": "_id",
    "as": "people",
    "depthField": "depth",
    "restrictSearchWithMatch": { "parent": { "$ne": null } }
  }}
])

返回相同的结果,但不包括"parent"字段为null的“根”文档。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "_id" : 5,
    "parent" : 4,
    "first" : "Mor",
    "last" : "Dor",
    "people" : [
        {
            "_id" : 2,
            "parent" : 1,
            "first" : "Jane",
            "last" : "Dor",
            "depth" : NumberLong(2)
        },
        {
            "_id" : 3,
            "parent" : 2,
            "first" : "Crane",
            "last" : "Dor",
            "depth" : NumberLong(1)
        },
        {
            "_id" : 4,
            "parent" : 3,
            "first" : "Ho",
            "last" : "Dor",
            "depth" : NumberLong(0)
        }
    ]
}

当然,同样的原则也适用于您的"last"条件,它只能匹配该条件为真的文档。这里我将展示这两个条件,但是$or是可选的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db.PeopleDb.aggregate([
  { "$match": { "_id": 5 } },
  { "$graphLookup": {
    "from": "PeopleDb",
    "startWith": "$parent",
    "connectFromField": "parent",
    "connectToField": "_id",
    "as": "people",
    "depthField": "depth",
    "restrictSearchWithMatch": {
      "$or": [
        { "parent": { "$ne": null }},
        { "last": "Dor" }
      ]
    }
  }}
])

然而,注意到认为"restrictSearchWithMatch"是一个“递归”条件,因此如果链中的任何“祖先”不满足"last"条件,那么链就会中断,并且无法检索进一步的祖先。为了获得“所有祖先”,但只显示那些具有匹配的"last"的人,那么您可以将结果数组内容改为$filter

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db.PeopleDb.aggregate([
  { "$match": { "_id": 5 } },
  { "$graphLookup": {
    "from": "PeopleDb",
    "startWith": "$parent",
    "connectFromField": "parent",
    "connectToField": "_id",
    "as": "people",
    "depthField": "depth",
  }},
  { "$addFields": {
    "people": {
      "$filter": {
        "input": "$people",
        "cond": { "$eq": [ "$$this.last", "Dor" ] }
      }
    }
  }}
])

或者通过与“祖先”相关的初始匹配文档的值进行“动态”比较,方法是使用字段值表达式而不是硬编码值:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
db.PeopleDb.aggregate([
  { "$match": { "_id": 5 } },
  { "$graphLookup": {
    "from": "PeopleDb",
    "startWith": "$parent",
    "connectFromField": "parent",
    "connectToField": "_id",
    "as": "people",
    "depthField": "depth",
  }},
  { "$addFields": {
    "people": {
      "$filter": {
        "input": "$people",
        "cond": { "$eq": [ "$$this.last", "$last" ] }
      }
    }
  }}
])

在这种情况下,它是相同的2,3,4祖先,但是如果说祖先3"last"具有不同的值,那么使用$filter实际上返回2,4,而"restrictSearchWithMatch"只返回4,因为3会“破坏链”。这就是主要的区别。

N.B你还不能使用$graphLookup做的一件事就是不允许“字段比较表达式”。如果您想要类似于这些路线的东西,那么如果您的实际意图确实是在递归搜索中不满足“字段比较”的情况下,那么您将对$filter进行进一步的操作,并可能执行其他操作,例如$indexOfArray

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50859425

复制
相关文章
[android] 手机卫士欢迎细节和主界面
<item name="android:windowNoTitle">true</item>
唯一Chat
2019/09/10
5090
用户登录界面[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/166531.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/20
3.3K0
用户登录界面[通俗易懂]
CSS——用户界面
用户界面(User Interface)属性是一些与用户界面特性相关的CSS属性。
Html5知典
2019/11/26
7240
SAP RETAIL 商品主数据POS视图
SAP RETAIL 商品主数据POS视图 SAP RETAIL系统上商品主数据有一个view叫做POS的,如下图示: 这个视图有啥用? 笔者检查了该视图里的字段,认为对业务起控制作用的字段主要有如下
SAP虾客
2021/11/05
4980
图形用户界面入门
EasyGUI 是 Python 中一个非常简单的 GUI 编程模块,不同于其他的 GUI 生成器,它不是事件驱动的。相反,所有的 GUI 交互都是通过简地函数调用就可以实现。
清菡
2020/12/02
9410
图形用户界面入门
[javaSE] GUI(图形用户界面)
调用Frame对象的setSize()方法,设置尺寸,参数:int的宽度,int的高度
唯一Chat
2019/09/10
9040
[javaSE] GUI(图形用户界面)
用户界面开发基础
Activity是Android中最核心的应用程序组件,也是大多数程序必须使用的用于显示界面的组件。
小小工匠
2021/08/16
1.8K0
模拟用户登录界面
上网过程中,我们常常会有一个账号的登录过程,本篇博客通过模拟用户登录界面以及登录过程过多时,引发的账号锁定现象。形象地变现出用户登录的详细过程。
算法与编程之美
2021/12/21
3.3K0
CSS用户界面样式
所谓的界面样式, 就是更改一些用户操作样式, 比如 更改用户的鼠标样式, 表单轮廓以及 防止表单域拖拽等。但是比如滚动条的样式改动受到了很多浏览器的抵制,因此我们就放弃了。
星辰_大海
2020/09/30
1.8K0
ABAP随笔-物料主数据界面增强
大家新年好,这个新年格外的不一样。在家远程办公的我忙着项目上的事,加上过年就一直忘记写随笔了。果然是一个佛系得运营,今天来个长一点得文章哈。
Tab Zhu
2022/06/23
1K0
ABAP随笔-物料主数据界面增强
electron仿制qq(2) 主界面制作
制作从头开始 最后会将写好的组件放到一起的! 之前写了好几天的纯css 有点累 本章中将使用sass 如果代码太长 会分两个或多个章节写 代码中会有详细的注释 以便于大家阅读and理解 界面可能会有部分偏差 比较是仿制的
李昊天
2019/05/26
1.5K0
postman系列(一):主界面模块解析
在做接口测试时经常会用到postman,但是一直没有总结过,太过零散,这次找了一些好的资料,结合自己平时所用到的功能,总结一波
冰霜
2022/03/15
8220
postman系列(一):主界面模块解析
后台管理系统界面_用户界面管理系统
3. FreshUI – Premium Web App and Admin Template
全栈程序员站长
2022/10/01
4.5K0
后台管理系统界面_用户界面管理系统
ectron仿制qq(3) 主界面制作(2)
这里解释下 -顶部header的高度(140) 底部的高度(40) 写法很多 不过达到效果就行了 在窗口拉伸的时候可以自适应高度
李昊天
2019/05/26
7240
Android用户界面开发概述
相信通过前面15期的学习,Android的开发环境已经基本掌握了,如果仍有问题,欢迎到Android零基础入门技术讨论微信群交流,从本期开始正式来一步一步踏入Android开发之路。 Android应用开发的一项内容就是用户界面的开发。Android提供了非常丰富的用户界面组件,借助于这些用户界面组件,开发者可以非常方便地进行用户界面开发,而且可以开发出非常优秀的用户界面。 一、界面UI元素介绍 Android应用是运行于手机系统上的程序,这种程序给用户的第一印象就是用户界面。接下
分享达人秀
2018/02/02
2.5K0
Android用户界面开发概述
Elasticsearch Cerebro 用户界面介绍
Cerebro 是查看分片分配和最有用的界面之一通过图形界面执行常见的索引操作。 完全开放源,并且它允许您添加用户,密码或 LDAP 身份验证问网络界面。Cerebro 是对先前插件的部分重写,并且可以作为自运行工具使用应用程序服务器,基于 Scala 的Play 框架。
HLee
2020/12/29
1K0
Elasticsearch Cerebro 用户界面介绍
MySQL存储过程,视图,用户管理
一张虚拟表,就是将一个经常被使用的查询作为一个虚拟表,开发者查询的时候不需要再次书写SQL,而是直接调用对应的视图就可,调用视图以后MySQL会执行这个查询SQL。
石的三次方
2021/01/05
9380
点击加载更多

相似问题

JHipster主细节用户界面

10

角用户界面-路由器继承视图

21

角用户界面路由器嵌套视图

14

角用户界面路由器生成两个用户界面视图

10

角用户界面路由器嵌套用户界面视图显示空白

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文