在前面的分享中,有讲解 “详解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. Main(string[] args)之args传递的几种方式

    1.通过配置project属性传递.如图: 2.通过代码传递 3.通过命令行传递

  2. 立即执行函数 IIFE

    立即执行函数表达式IIFE(Immediately-invoked function expression)我们知道,在javascript(ES5)中,是没有块级作用域的概念的.看一个例子 for ...

  3. SQL - Order By如何处理NULL

    问题来了.执行SQL语句 SELECT * FROM tbl ORDER BY x, y 如果用来排序的列x.y当中有NULL值,那么它们的顺序是怎样的呢? 不同的数据库有不同的答案,目前的主流数据库 ...

  4. SQLServer之附加数据库

    附加数据库注意事项 必须首先分离数据库. 尝试附加未分离的数据库将返回错误. 附加数据库时,所有数据文件(MDF 文件和 LDF 文件)都必须可用. 如果任何数据文件的路径不同于首次创建数据库或上次附 ...

  5. Linux 桌面玩家指南:16. 使用 CUDA 发挥显卡的计算性能

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  6. Linux 网络命令必知必会之 tcpdump,一份完整的抓包指南请查收!

    目录 01 简介 02 tcpdump 命令选项 03 过滤器 04 常用操作 4.1 抓取某主机的数据包 4.2 抓取某端口的数据包 4.3 抓取某网络(网段)的数据包 4.4 抓取某协议的数据包 ...

  7. jdk安装 java环境配置

    登录http://www.oracle.com,下载JDK(J2SE) JDK 1.0,1.1,1.2,1.3,1.4 1.5 (JDK5.0) à支持注解.支持泛型 1.6(JDK6.0) à Se ...

  8. Nosql与关系型数据库不同的使用场景

    Nosql 1.适合存储非结构化数据存储,数据量且不可预期.如:评论,文章 2.排行榜数据获取,实时更新的数据.如:游戏榜排名,用户投票 3.限时抢购活动.如:淘宝抢购活动 4.反垃圾系统.如:敏感词 ...

  9. 老毛桃pe安装系统

    1.准备一个空白U盘,插入电脑. 2.下载老毛桃pe 3.下载完成后,打开老毛桃,默认制作成系统盘,傻瓜操作,无需修改参数 4.打开浏览器,下载要安装的系统 www.msdn.itellyou.cn ...

  10. 中国.NET:各地微软技术俱乐部汇总(更新中...)

    与微软技术的发展历程相似,微软俱乐部的发展同样经历着沉沉浮浮.2002年周庆麒先生创办的著名Office技术论坛Excel Home的上线,各种线上技术社区在中国的互联网世界中萌发.接着以鞠海洋(广州 ...