MongoDB移除或限制字段条件聚合

时间:2019-05-03 08:49:20

标签: mongodb mongoose mongodb-query aggregation-framework

我在编写查找/汇总mongo查询时遇到问题,我的要求是获取所有文档,但条件如下:

假设我有2个文档:

{
  _id: 5ccaa76939d95d395791efd2,
  name: 'John Doe',
  email: 'john.doe@foobar.com',
  private: true
}

{
  _id: 5ccaa76939d95d395791efd2,
  name: 'Jane Doe',
  email: 'jane.doe@foobar.com',
  private: false
} 

现在我要查询的查询是字段private是否为真,那么当我查询时,如果private为真,我必须获取除电子邮件字段以外的所有文档,例如:

{
 _id: 5ccaa76939d95d395791efd2,
 name: 'John Doe',
 private: true
}

{
 _id: 5ccaa76939d95d395791efd2,
 name: 'Jane Doe',
 email: 'jane.doe@foobar.com',
 private: false
} 

在aggregate()中尝试了$redact$cond$$PRUNE$$DESCEND,还遇到了$$REMOVE(看起来是最新功能),但是无法获得所需的输出。请通过

帮助我

2 个答案:

答案 0 :(得分:4)

您可以使用$$REMOVE从返回的文档中删除字段。

db.collection.aggregate([ 
  { "$addFields": {
    "email": {
      "$cond": [
        { "$eq": ["$private", true] },
        "$$REMOVE",
        "$email"
      ]
    }
  }}
])

MongoPlayground

答案 1 :(得分:0)

谢谢安东尼·温兹莱特(Anthony Winzlet),他的解决方案就像一个魅力。

如果任何人都遇到同样的问题,并且需要包含多个字段,我可以通过编写以下方法来做到这一点:

function condition(privateFieldLimitationArray, publicFieldLimitationArray) {
  const condition = {};

  privateFieldLimitationArray.map((d, i) => {
    condition[d] = {
      "$cond": [
      { "$eq": ["$private", true] },
      "$$REMOVE",
      publicFieldLimitationArray.includes(d) ? '$$REMOVE' : '$'+d
      ]
    }
  });

  return condition;
}

然后,您可以使用上述功能,例如:

const privateLimitationArray = ['updatedAt', 'createdAt', 'email', 'lname', 'friendslist', '__v'];

const publicLimitationArray = ['updatedAt', 'createdAt', '__v'];


YourModel.aggregate([
        {
          $match: {
            // Your query to find by
          }
        }, {
          "$addFields": condition(privateLimitationArray, publicLimitationArray)
        }
    ])
    .then(result => {
      // handle result
    })
    .catch(error => {
      // handle error
    });