MongoDB 集合间关联查询后通过$filter进行筛选

在前面的分享中,有讲解 “详解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"的数据(子文档)。

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

原文地址:https://www.cnblogs.com/xuliuzai/p/10400368.html

时间: 2024-10-12 02:40:30

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

SQL中Update...Select...的使用,关联查询后进行更新数据

最常用的update语法是: UPDATE <table_name> SET <column_name1> = <value>,SET <column_name2> = <value> 如果我的更新值Value是从一条select语句拿出来,而且有很多列的话,用这种语法就很麻烦 第一,要select出来放在临时变量上,有很多个哦 第二,再将变量进行赋值. 列多起来非常麻烦,能不能像Insert那样,把整个Select语句的结果进行插入呢?就好象下

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

一.数据控制 mongodb操作数据量控制,千万控制好,不要因为操作的数据量过多而导致失败. 演示一下发生此类错误的错误提示: 二.多表关联查询实现 /* 声明变量bridge,用来记录两个集合所连接的桥梁. 相当于sql语句中的Join on语句,on后边跟的条件. 有了桥梁以后,再进行关联那就是易如反掌的事情啦. 关联桥梁所存储的数据是什么样的类型就需要根据你自己的需求来进行创建了. 我这里用一个对象来作为桥梁,然后调用对象中的属性. */ var bridge = db.info.find

MongoDB之DBref(关联插入,查询,删除) 实例深入

MongoDB之DBref(关联插入,查询,删除) 实例深入 如图所示,A,B,C三个Collection互相关联. 其中的数字为document的value值. 关于DBref的入门可以看http://blog.csdn.net/crazyjixiang/article/details/6616678这篇文章. 我们先建立A collection. Cpp代码 > var a={value:"1"} > var b={value:"2"} > v

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

如题: 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句不是一条关联查询语句. 例如: $list = $db->relation(true)->where($where)->order('blogid desc')->limit($Page->firstRow.','.$Page->listRows)->select(); $sql = $db->getLastSql(); 输出的sql语句为: SELE

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

知识点:查询一个实体类,并查出这个类下面的集合 Employee.java实体类 package com.hand.mybatis.bean;public class Employee {    private Integer eId;    private String eName;    private Integer gender;    private String email;    private Department dept;        public Employee() {

RDIFramework.NET 中多表关联查询分页实例

RDIFramework.NET 中多表关联查询分页实例 RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用户和开发者最佳的.Net框架部署方案.该框架以SOA范式作为指导思想,作为异质系统整合与互操作性.分布式应用提供了可行的解决方案. 分页非常的常见,基本任何项目都会涉及到分页,这没什么好谈的,大多数我们分页对单表的分页比较多,对多表的分页我们可以通过视图来实现,当然还有其他的方式,在这儿,我以一个实例展示下使用我们的RDIFramework.NET来实现多表

Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o

Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o 1. Criteria,,Criterion ,, 1 <2. 主要的对象黑头配置磊个关联,三 1 3. Criteria 黑头配置关联查询了... 2 4. Ati Meata 配置关联 @CriteriaRelt 2 5. 关联createCriteria() 3 6. Criteria的使用outline 4 7. 参考:: 5 1. Criteria,,Criterion ,,

Ibatis组合键关联查询

在使用Ibatis时,会经常遇到关联查询,一般有两种解决方案: 使用代码进行关联查询 使用Ibatis配置文件进行关联查询 使用代码进行关联查询不作解释,本次主要是针对Ibatis配置文件进行关联查询进行探究,如发现有问题或不当之处还请不吝赐教! 对于Ibatis配置文件进行关联查询,下面举一个例子进行辅助描述: 假设有这样一个需求:某一网站页面需要展示文章,文章有两种不同的类别,分别为A1.A2,在每篇文章后都会跟随一些相关的商品,同一商品可关联任意类别文章. 分析该需求可得知,文章一张表,相

MyBatis关联查询、多条件查询

1.一对一查询 任务需求; 根据班级的信息查询出教师的相关信息 1.数据库表的设计 班级表: 教师表: 2.实体类的设计 班级表: public class Classes { 9     //定义实体类的属性,与class表中的字段对应 10     private int id;            //id===>c_id 11     private String name;    //name===>c_name 13     /** 14      * class表中有一个tea