在前面的分享中,有讲解 “详解MongoDB中的多表关联查询($lookup)” 一节,其内容涵盖了常见的集合管理的需求。我们知道文档的选择都是通过$match进行匹配刷选。但这是文档间的匹配筛选,并没有对单个新生成的文档进行内嵌子文档进行筛选。

那么什么是$lookup后新文档的内嵌子文档呢?

假设有以下2个集合,一个是商品库存集合 inventory,存储的测试数据 如下:

db.inventory.insert([
{ "_id" : 1, "sku" : "almonds", product: "product 1", "instock" : 120 },
{ "_id" : 2, "sku" : "bread1", product: "product 2", "instock" : 80 },
{ "_id" : 3, "sku" : "bread2", product: "product 2", "instock" : 80 },
{ "_id" : 4, "sku" : "pecans1", product: "product 4", "instock" : 70 },
{ "_id" : 5, "sku" : "pecans2", product: "product 4", "instock" : 70 },
])

一个是商品对应的原料集合product,存储的测试数据,如下。

db.product.insert([
{ "_id" : 1, product: "product 1", description: "金玉满堂1" },
{ "_id" : 2, product: "product 2", description: "招财进宝"},
{ "_id" : 3, product: "product 4", description: "杨柳依依"},
])

两个集合都包含有product 字段,如果 需求是按原料名称统计每个原料对应的商品情况。

可以根据字段product进行集合关联,并且product集合的文档与inventory 集合的文档是 一对多 的关系。

执行关联脚本查询的脚本如下:

db.product.aggregate([
{
$lookup:
{
from: "inventory",
localField: "product",
foreignField: "product",
as: "inventory_docs"
}
}
])

新生成的聚合集合的文档如下:

/* 1 */
{
"_id" : 1,
"product" : "product 1",
"description" : "金玉满堂1",
"inventory_docs" : [
{
"_id" : 1,
"sku" : "almonds",
"product" : "product 1",
"instock" : 120,
"state" : "OK"
}
]
}, /* 2 */
{
"_id" : 2,
"product" : "product 2",
"description" : "招财进宝",
"inventory_docs" : [
{
"_id" : 2,
"sku" : "bread1",
"product" : "product 2",
"instock" : 80,
"state" : "OK"
},
{
"_id" : 3,
"sku" : "bread2",
"product" : "product 2",
"instock" : 80,
"state" : "Simple"
}
]
}, /* 3 */
{
"_id" : 3,
"product" : "product 4",
"description" : "杨柳依依",
"inventory_docs" : [
{
"_id" : 4,
"sku" : "pecans1",
"product" : "product 4",
"instock" : 70,
"state" : "OK"
},
{
"_id" : 5,
"sku" : "pecans2",
"product" : "product 4",
"instock" : 70,
"state" : "Simple"
}
]
}

从返回结果可以看出,

(1) 返回的文档数量和.aggreate的集合文档数量一样(即外面的那个集合,而不是新字段的From的那个集合)。

(2)关联的主要功能是将每个输入待处理的文档,经过$lookup 阶段的处理,输出的新文档中会包含一个新生成的数组列(户名可根据需要命名新key的名字 )。数组列存放的数据 是 来自 被Join 集合的适配文档,如果没有,集合为空(即 为[ ])。

注意新的字段的类型是数组的形式,一对多的时候,新字段就是就是明显的内嵌子文档。

我们看到新文档的字段 inventory_docs ,它由两个 内嵌 子文档组成,

"inventory_docs" : [
{
"_id" : 4,
"sku" : "pecans1",
"product" : "product 4",
"instock" : 70,
"state" : "OK"
},
{
"_id" : 5,
"sku" : "pecans2",
"product" : "product 4",
"instock" : 70,
"state" : "Simple"
}
]

那么如何根据要求筛选符合要求的子文档呢?$match是不可以的,这时候可以通过$filter。

代码如下:

db.product.aggregate([
{
$lookup:
{
from: "inventory",
localField: "product",
foreignField: "product",
as: "inventory_docs"
}
}
,
{
$project: {
inventory_docs: {
$filter: {
input: "$inventory_docs",
as: "item",
cond: { $eq: [ "$$item.state", "OK"
] }
}
}
}
}

])

结果显示如下:

/* 1 */
{
"_id" : 1,
"inventory_docs" : [
{
"_id" : 1,
"sku" : "almonds",
"product" : "product 1",
"instock" : 120,
"state" : "OK"
}
]
}, /* 2 */
{
"_id" : 2,
"inventory_docs" : [
{
"_id" : 2,
"sku" : "bread1",
"product" : "product 2",
"instock" : 80,
"state" : "OK"
}
]
}, /* 3 */
{
"_id" : 3,
"inventory_docs" : [
{
"_id" : 4,
"sku" : "pecans1",
"product" : "product 4",
"instock" : 70,
"state" : "OK"
}
]
}

从结果可以看出,数组子文档 没有了state:"Simple"的数据(子文档)。

本文版权归作者所有,未经作者同意不得转载,谢谢配合!!!

MongoDB 集合间关联查询后通过$filter进行筛选的更多相关文章

  1. 详解MongoDB中的多表关联查询($lookup)

    一.  聚合框架 聚合框架是MongoDB的高级查询语言,它允许我们通过转换和合并多个文档中的数据来生成新的单个文档中不存在的信息. 聚合管道操作主要包含下面几个部分: 命令 功能描述 $projec ...

  2. Mongoose 两个表关联查询aggregate 以及 Mongoose中获取ObjectId

    Mongoose 两个表关联查询aggregate 通常两个表关联查询的时候,是一种一对多的关系,比如订单与订单详情就是一对多的关系,一个订单下面有多个商品 数据模拟 首先我们先将数据模拟出来,先选择 ...

  3. C#代码中实现两个表(DataTable)的关联查询(JOIN)

    之前通常都是使用SQL直接从数据库中取出表1和表2关联查询后的数据,只需要用一个JOIN就可以了,非常方便.近日遇到一种情况,两个表中的数据已经取到代码中,需要在代码中将这两个表关联起来,并得到它们横 ...

  4. Mybatis高级查询之关联查询

    learn from:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps 关联查询 准备 关联结果查询(一对一) resul ...

  5. mongodb操作之使用javaScript实现多表关联查询

    一.数据控制 mongodb操作数据量控制,千万控制好,不要因为操作的数据量过多而导致失败. 演示一下发生此类错误的错误提示:

  6. 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句

    如题: 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句不是一条关联查询语句. 例如: $list = $db->relation(true) ...

  7. 多表关联查询_resultMap_集合对象

    多表关联查询_resultMap_集合对象_N+1方式实现 package com.bjsxt.mapper; import java.util.List; import com.bjsxt.pojo ...

  8. mybatis映射文件select_resultMap_关联查询_collection定义关联集合

    知识点:查询一个实体类,并查出这个类下面的集合 Employee.java实体类 package com.hand.mybatis.bean;public class Employee {    pr ...

  9. MongoDB学习-->Gridfs分布式存储&DBRef关联查询

    mongodb自带的一个分布式文件系统 fs.files _id filename md5 size uploaddate contenttype metadata {"user_id&qu ...

随机推荐

  1. 深度学习之Numpy整理

    一.Numpy介绍.为什么要用Numpy 1.Numpy介绍 Numpy是Python的一个扩展包,语法和Matlab有很多相似之处.它支持高维数组和矩阵运算,也提供了许多数组和矩阵运算的函数.另外, ...

  2. 使用Ninject的一般步骤

    以下为DI控制反转个人理解烦请各位大牛指教~ 编写程序时我们应当遵循抵耦合高内聚的原则(各个功能模块互不依赖). 我们可以利用面向对象里面接口的特性来进行DI控制反转,让功能模块全部依赖接口,而不依赖 ...

  3. css常见的各种布局下----三列布局

    css 三列布局,左右固定宽度右边自适应 1不使用定位,只使用浮动可以实现左右固定,中间宽度自适应布局 1.1.1 自适应部分一定要放第一个位子,使用浮动,并且设置宽度为100%,不设置浮动元素内容不 ...

  4. 还在用AIDL吗?试试EasyMessenger吧

    EasyMessenger 直达Github项目地址 一款用于Android平台的基于Binder的进程间通信库,采用annotationProcessor生成IPC通信需要的代码.EasyMesse ...

  5. 云计算CRM软件厂商,你青睐哪家?

    2018年CRM系统软件市场风起云涌,国内外厂商群雄逐鹿.2019年,新一轮的角逐已然展开.据Gartner报告称,CRM客户关系管理系统在2017年全球的销售额首次超越数据库管理系统((Databa ...

  6. SQL Server获取连续区间的日期

    个人理解的方法有三种 通过系统表master..spt_values获取 用WHILE循环获取 游标获取 CET递归(感谢评论区博友) 方法一:通过系统表master..spt_values获取 1. ...

  7. CF914G Sum the Fibonacci FWT、子集卷积

    传送门 一道良心的练习FWT和子集卷积的板子-- 具体来说就是先把所有满足\(s_a \& s_b = 0\)的\(s_a \mid s_b\)的值用子集卷积算出来,将所有\(s_a \opl ...

  8. .NET Core 2.1来了!

    太棒了! .NET Core 2.0正式发布至今已经过去了大半年,这大半年说长不长说短不短,这段时间里,我是充分地体会到了微软的诚意,那就是认认真真打造一个优秀的开源平台.这大半年的时间里,微软一直在 ...

  9. for in 使用

    // JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写. var json = { "id": 1, "n ...

  10. spring的核心组件及作用(一)

    Spring的核心组件有: Context     Core     Bean. 如果要在这三个核心组件上挑出一个最核心的组件,那就是Bean组件了. Spring的特性功能有:WEB ORM AOP ...