经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MongoDB » 查看文章
MongoDB 集合间关联查询后通过$filter进行筛选
来源:cnblogs  作者:东山絮柳仔  时间:2019/2/20 9:29:14  对本文有异议

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

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

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

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

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

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

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

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

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

  1. db.product.aggregate([
  2. {
  3. $lookup:
  4. {
  5. from: "inventory",
  6. localField: "product",
  7. foreignField: "product",
  8. as: "inventory_docs"
  9. }
  10. }
  11. ])

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

  1. /* 1 */
  2. {
  3. "_id" : 1,
  4. "product" : "product 1",
  5. "description" : "金玉满堂1",
  6. "inventory_docs" : [
  7. {
  8. "_id" : 1,
  9. "sku" : "almonds",
  10. "product" : "product 1",
  11. "instock" : 120,
  12. "state" : "OK"
  13. }
  14. ]
  15. },
  16. /* 2 */
  17. {
  18. "_id" : 2,
  19. "product" : "product 2",
  20. "description" : "招财进宝",
  21. "inventory_docs" : [
  22. {
  23. "_id" : 2,
  24. "sku" : "bread1",
  25. "product" : "product 2",
  26. "instock" : 80,
  27. "state" : "OK"
  28. },
  29. {
  30. "_id" : 3,
  31. "sku" : "bread2",
  32. "product" : "product 2",
  33. "instock" : 80,
  34. "state" : "Simple"
  35. }
  36. ]
  37. },
  38. /* 3 */
  39. {
  40. "_id" : 3,
  41. "product" : "product 4",
  42. "description" : "杨柳依依",
  43. "inventory_docs" : [
  44. {
  45. "_id" : 4,
  46. "sku" : "pecans1",
  47. "product" : "product 4",
  48. "instock" : 70,
  49. "state" : "OK"
  50. },
  51. {
  52. "_id" : 5,
  53. "sku" : "pecans2",
  54. "product" : "product 4",
  55. "instock" : 70,
  56. "state" : "Simple"
  57. }
  58. ]
  59. }

从返回结果可以看出,

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

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

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

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

  1. "inventory_docs" : [
  2. {
  3. "_id" : 4,
  4. "sku" : "pecans1",
  5. "product" : "product 4",
  6. "instock" : 70,
  7. "state" : "OK"
  8. },
  9. {
  10. "_id" : 5,
  11. "sku" : "pecans2",
  12. "product" : "product 4",
  13. "instock" : 70,
  14. "state" : "Simple"
  15. }
  16. ]

 

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

代码如下:

  1. db.product.aggregate([
  2. {
  3. $lookup:
  4. {
  5. from: "inventory",
  6. localField: "product",
  7. foreignField: "product",
  8. as: "inventory_docs"
  9. }
  10. }
  11. ,
  12. {
  13. $project: {
  14. inventory_docs: {
  15. $filter: {
  16. input: "$inventory_docs",
  17. as: "item",
  18. cond: { $eq: [ "$$item.state", "OK" ] }
  19. }
  20. }
  21. }
  22. }
  23. ])

结果显示如下:

  1. /* 1 */
  2. {
  3. "_id" : 1,
  4. "inventory_docs" : [
  5. {
  6. "_id" : 1,
  7. "sku" : "almonds",
  8. "product" : "product 1",
  9. "instock" : 120,
  10. "state" : "OK"
  11. }
  12. ]
  13. },
  14. /* 2 */
  15. {
  16. "_id" : 2,
  17. "inventory_docs" : [
  18. {
  19. "_id" : 2,
  20. "sku" : "bread1",
  21. "product" : "product 2",
  22. "instock" : 80,
  23. "state" : "OK"
  24. }
  25. ]
  26. },
  27. /* 3 */
  28. {
  29. "_id" : 3,
  30. "inventory_docs" : [
  31. {
  32. "_id" : 4,
  33. "sku" : "pecans1",
  34. "product" : "product 4",
  35. "instock" : 70,
  36. "state" : "OK"
  37. }
  38. ]
  39. }

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

 

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

原文链接:http://www.cnblogs.com/xuliuzai/p/10400368.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号