计算嵌套字段的出现次数

时间:2018-07-23 11:59:22

标签: node.js mongodb mongoose

我正在尝试计算嵌套字段中具有匹配条件的文档数。

我的架构定义如下:

let userSchema = new Schema({
  //...
  interests: [{
    type: Schema.Types.ObjectId,
    ref: 'Interests'
  }],
  //...
});

let interestSchema = new Schema({
  id: ObjectId,
  name: {
    type: String,
    required: true
  },
  //...
});

计数必须反映用户选择同名兴趣的次数。

例如,在以下文档中,我必须将结果“ 2”与“编码”相关:

{
  //Other Fields of user 1
  "interests": [
     {
       "id": "XXX"
       "name": "coding"
     }, 
     {
       "id": "YYY"
       "name": "surfing"
     }]
}

{
  //Other Fields of user 2
  "interests": [
     {
       "id": "ZZZ"
       "name": "coding"
     }
   ]
}

我研究了countDocuments方法,但似乎不允许这种计数。


编辑+第一个解决方案:

这是我设法解决的方法:

const res = await UserModel.aggregate([
  {
    $unwind: '$interests'
  },
  {
    $lookup: {
      from: "interests",
      localField: "interests",
      foreignField: "_id",
      as: "interests"
    }
  },
  {
    $match:{
      "interests.name": name
    }
  },
  {
    $count: "count"
  }
]);
return res[0].count;

利益是引用类型这一事实,除非经过lookup阶段,否则我无法查询其名称。我不确定这是否是一个有关性能的好解决方案,因为unwind阶段必须遍历数据库的所有用户并为他们的每个兴趣创建一个新元素。这就是为什么我不将其发布为答案的原因

1 个答案:

答案 0 :(得分:0)

要使用elemMatch,我必须更改架构以便将Interest嵌入User中而不是引用它:

let userSchema = new Schema({
  //...
  interests:  [InterestSchema],
  //...
});

let InterestSchema = new Schema({
  id: ObjectId,
  name: {
    type: String,
    required: true
  },
  //...
});

这就是我使用elemMatch的方式:

const count = UserModel
  .where('interests').elemMatch( interest => {
    interest.where({ name: name });
  })
  .count();

正如我在问题中提到的,聚合method可以工作,但是由于我使用的是引用数组而不是子文档,因此我不确定其性能,这就是为什么我必须更改我的收藏