【问题标题】:How to query two collections that have a "one-to-many" relationship in MongoDB?如何在MongoDB中查询两个具有“一对多”关系的集合?
【发布时间】:2021-05-08 18:32:43
【问题描述】:

我们有两个系列:“houses”和“events”。 house 集合中的每个文档都包含一个“events”字段,其中包含一组引用事件的 id(“一对多强>”关系)。数组可以为空。

房子”架构:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const HouseSchema = new Schema({
  name: String,
  district: String,
  locality: String,
  date: {
    type: Date,
    default: Date.now
  },
  events: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Event'
  }]
});

module.exports = mongoose.model('House', HouseSchema);

事件”架构:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const EventSchema = new Schema({
  event: String,
  details: String,
  date: {
    type: Date,
    default: Date.now
  },
  house: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'House'
  }
});

module.exports = mongoose.model('Event', EventSchema);

我需要同时查询“房屋”和“事件”,并找到那些具有符合所有条件的引用“事件”的“房屋”。我将提供几个查询选项。

仅使用来自“房屋”的参数进行查询。假设“houses”集合中有两个文档满足条件{"locality": "Facebook"}。结果应该是这样的:

[
  {
    "_id": "601bae8e26ed00591d571dbe",
    "name": "Facebook testing department",
    "district": "Los-Angeles",
    "locality": "Facebook",
    "events": [
      {
        "_id": "601bae8e26ed00591d571dbf",
        "event": "Testing",
        "details": "Testing software for production",
        "date": "2020-07-31T21:00:00.000Z"
      }
    ]
  },
  {
    "_id": "601bae8e26ed00591d571dbc",
    "name": "Facebook office",
    "district": "Los-Angeles",
    "locality": "Facebook",
    "events": [
      {
        "_id": "601bae8e26ed00591d571dbd",
        "event": "Conference",
        "details": "Developers conference about 12345",
        "date": "2020-07-31T21:00:00.000Z"
      }
    ]
  },
];

仅针对“事件”使用参数进行查询。假设“事件”集合中有两条记录满足条件{"event": "Conference"}。结果是:

[
  {
    "_id": "601bae8e26ed00591d571dbc",
    "name": "Facebook office",
    "district": "Los-Angeles",
    "locality": "Facebook",
    "events": [
      {
        "_id": "601bae8e26ed00591d571dbd",
        "event": "Conference",
        "details": "Developers conference about 12345",
        "date": "2020-07-31T21:00:00.000Z"
      }
    ]
  },
  {
    "_id": "601bae8e26ed00591d571dba",
    "name": "Oxford",
    "district": "London",
    "locality": "Oxford",
    "events": [
      {
        "_id": "601bae8e26ed00591d571dbb",
        "event": "Conference",
        "details": "About something",
        "date": "2020-07-31T21:00:00.000Z"
      }
    ]
  },
];

使用“房屋”和“事件”的参数进行查询。如果我们查询的条件是{"locality": "Facebook", "event": "Conference"},那么结果应该是这样的:

[  
  {
    "_id": "601bae8e26ed00591d571dbc",
    "name": "Facebook office",
    "district": "Los-Angeles",
    "locality": "Facebook",
    "events": [
      {
        "_id": "601bae8e26ed00591d571dbd",
        "event": "Conference",
        "details": "Developers conference about 12345",
        "date": "2020-07-31T21:00:00.000Z"
      }
    ]
  },
];

我遇到过类似的情况,需要使查询比平时更复杂。但是在这里,我们需要根据参数对一个或两个集合进行查询,结果,我们应该得到带有对应查询参数的嵌套“事件”的“房屋”。我不太了解 MongoDB 聚合,希望能提供帮助。

【问题讨论】:

    标签: javascript node.js mongodb mongoose aggregation-framework


    【解决方案1】:
    • 声明您的输入
    let locality = req.body.locality;
    let event = req.body.event;
    
    • 初始化聚合管道(将 HousesModel 替换为您的 reql 模型名称)
    let p = HousesModel.aggregate();
    
    • 检查locality 的条件
    if (locality && locality.trim()) p.match({ locality: locality });
    
    • $lookup 有管道,
    • events数组声明为let
    • 匹配表达式中的事件条件
    • 如果事件搜索可用,则检查条件,然后放置条件
    p.lookup({
      from: "events", // replace your actual collection name if this is wrong
      let: { events: "$events" },
      pipeline: [
        {
          $match: {
            $and: [
              { $expr: { $in: ["$_id", "$$events"] } },
              (event && event.trim() ? { event: event } : {})         
            ]
          }
        }
      ],
      as: "events"
    });
    
    • 确保事件不为空
    p.match({ events: { $ne: [] } });
    
    • 在管道上方执行
    let result = await p.exec();
    

    Playground

    按顺序组合以上代码进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 2020-09-11
      • 1970-01-01
      • 2013-05-29
      • 2012-05-11
      • 1970-01-01
      相关资源
      最近更新 更多