【问题标题】:Mongoose Returning null Reference of Property on QueryMongoose 在查询中返回空属性引用
【发布时间】:2022-06-14 22:12:09
【问题描述】:

我在 Mongoose 中定义了两个简单模型,由两个模式 Client 和 City 组成,我在 Client 中将属性 city 定义为 ObjectId,参考:'City',到目前为止一切顺利。

如果我查询客户并且还想按 City 的“省”属性进行过滤,我会这样做:

const client = await Client
    .find({ name: "Gérard" })
    .populate([{
        path: 'city',
        model: City,
        match: { province: 'BA' }
    }]);

而且输出很好:

{
  "id": "627264e3ec261a883d42ead9",
  "name": "Gérard",
  "email": "gerard@depardieu.fr",
  "date": "1948-12-27",
  "active": true,
  "city": {
    "id": "627264e3ec261a883d42ead1",
    "name": "Buenos Aires",
    "province": "BA"
  }
}

但是,如果我输入一个不存在的城市的省代码:

const client = await Client
    .find({ name: "Gérard" })
    .populate([{
        path: 'city',
        model: City,
        match: { province: 'CA' }
    }]);

它返回给我这个:

{
  "id": "627264e3ec261a883d42ead9",
  "name": "Gérard",
  "email": "gerard@depardieu.fr",
  "date": "1948-12-27",
  "active": true,
  "city": null
}

在这种特殊情况下,我不希望返回任何 Client 实例,而且我不知道如何使用 Mongoose 避免这种行为,例如,我从来不必担心 Spring Data 的这种行为。

这里有人告诉我在我的代码中做这样的事情:

const client = await Client
    .find({ name: "Gérard" })
    .populate([{
        path: 'city',
        model: City,
        match: { province: 'CA' }
    }]);

if(client && client.city){

   return client; //or pass it to the response... whatever...
}

但是,假设这个查询是在一个拥有数百万客户的集合上完成的,上面的代码非常浪费资源,我什至不会开始讨论它有什么问题(好吧,你可以想象有多少客户不在“CA”省,数据库服务器将发送到我的应用服务器只是为了被拒绝......)。

如果那个城市/省不匹配,我想要的是根本不返回任何客户。

一个例子是模拟 SQL:

SELECT * FROM CLIENT JOIN CITY ON CITY.ID=CLIENT.CITY_ID WHERE CITY.PROVINCE = 'CA' 

这里没有客户返回,一旦数据库中唯一的客户有它的省 = 'BA'。

那么,怎么做呢?

提前致谢。

【问题讨论】:

    标签: javascript node.js mongoose mongodb-query


    【解决方案1】:

    我自己解决了这个问题,我不得不使用 Mongoose 降低一点级别并使用聚合和查找。

    const client = await Client.aggregate([
      { 
        $match: { name: "Gérard" } 
      },
      {
        $lookup: {
          from: City.collection.name,
          pipeline: [
            {
              $match: {
                province: 'BA'
              }
            }
          ], as: "city"
        }
      },
      {
         $unwind: "$city"
      },
      {
         $match: {
           city: { $ne: [] }
         }
       }
    ]);
    

    预期结果:

    {
      "id": "627264e3ec261a883d42ead9",
      "name": "Gérard",
      "email": "gerard@depardieu.fr",
      "date": "1948-12-27",
      "active": true,
      "city": {
        "id": "627264e3ec261a883d42ead1",
        "name": "Buenos Aires",
        "province": "BA"
      }
    }
    

    女巫没事,客户名称“Gérard”住在“布宜诺斯艾利斯”,位于“BA”省。

    另一方面:

    const client = await Client.aggregate([
      { 
        $match: { name: "Gérard" } 
      },
      {
        $lookup: {
          from: City.collection.name,
          pipeline: [
            {
              $match: {
                province: 'CA'
              }
            }
          ], as: "city"
        }
      },
      {
         $unwind: "$city"
      },
      {
         $match: {
           city: { $ne: [] }
         }
       }
    ]);
    

    一旦“布宜诺斯艾利斯”市不在“CA”省,则不返回任何内容。

    注意这里传递给 Client.aggregate() 的数组接收的最后一个参数(作为对象):

    {
      $match: {
        city: { $ne: [] }
      }
    }
    

    这告诉 MongoDB,为了返回数据,城市必须不等于空数组。

    这样问题就解决了。

    【讨论】:

      猜你喜欢
      • 2019-08-29
      • 2018-06-12
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 2021-07-22
      • 1970-01-01
      • 2019-11-30
      • 2013-11-25
      相关资源
      最近更新 更多