猫鼬通过长度斗争来填充和排序

时间:2017-03-10 17:47:24

标签: mongodb mongoose mongodb-query aggregation-framework

我有以下mongoose架构:

const userSchema = new mongoose.Schema({
  email: { type: String, unique: true },
  fragments: [{type: mongoose.Schema.Types.ObjectId, ref: 'Fragment'}]
}, { timestamps: true, collection: 'user' });

const fragmentSchema = new mongoose.Schema({
  text: String,
  owner: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
}, { timestamps: true, collection: 'fragment' });

在数据中,我在Fragment中有引用,但在User中没有引用:

用户:

{
    "_id" : ObjectId("58373e571cbccb010012bfcd"),
    "email" : "email@example.com",
    // no "fragments": [ObjectId('58075ce37b7f2f01002b718f')] etc.
}

片段:

{
    "_id" : ObjectId("58075ce37b7f2f01002b718f"),
    "text" : "Donc, il faut changer de méthode",
    "owner" : ObjectId("58075ce27b7f2f01002b717f")
}

我想查询按片段数量排序的用户,我无法实现这一点......

首先,我想做这项工作:

User.find({_id: '58075ce27b7f2f01002b717f'})
  .populate('fragments').exec(console.log)

返回

{ 
  _id: 58075ce27b7f2f01002b717f,
  email: 'bububg@hotmail.fr',
  fragments: []
}

虽然我至少应该包含上述fragment

关于排序查询,这是我现在的位置:

User.aggregate([
  { "$project": {
    "email": 1,
    "fragments": 1,
    "nbFragments": { "$size": { "$ifNull": [ "$fragments", [] ] } }
  }},
  { "$sort": { "nbFragments": -1 } }
], console.log)

至少它运行,但所有nbFragments字段都设置为0.这可能与.populate('fragments')不起作用的事实有关,但我无法确定。

感谢您的帮助,我没想到使用Mongodb会有这么多麻烦...

编辑:感谢@Veeram,遗憾的是你的解决方案无效:

User.find({}).find({_id: '58075ce27b7f2f01002b717f'}).populate('fragments').exec(console.log)
[ { _id: 58075ce27b7f2f01002b717f,
    email: 'email@example.com',
    // no fragments entry
} ] 

当我更新我的架构时:

userSchema.virtual('fragments', {
  ref: 'Fragment',
  localField: '_id',
  foreignField: 'owner',
  options: { sort: { number: 1 }}, // Added sort just as an example
});

关于汇总,用:

User.aggregate([{
  $lookup: {
    from: 'Fragment',
    localField: '_id',
    foreignField: 'owner',
    as: 'fragments'
  }
}, { "$project": {
  "email": 1,
  "fragments": 1,
  "nbFragments": {
    "$size": { "$ifNull": [ "$fragments", [] ] } }
}}, { "$sort": { "nbFragments": -1 } }
]).exec(console.log)

我明白了:

{ 
  _id: 58075ce27b7f2f01002b717f,
  email: 'email@example.com',
  fragments: [] // fragments are always empty while they shouldn't!
}

1 个答案:

答案 0 :(得分:0)

使用以下数据进行测试

User:

{
    "_id" : ObjectId("58373e571cbccb010012bfcd"),
    "email" : "email@example.com"
}

Fragment:

{
    "_id" : ObjectId("58075ce37b7f2f01002b718f"),
    "text" : "Donc, il faut changer de méthode",
    "owner" : ObjectId("58373e571cbccb010012bfcd")
}

响应

[{"_id":"58373e571cbccb010012bfcd","email":"email@example.com","fragments":[{"_id":"58075ce37b7f2f01002b718f","text":"Donc, il faut changer de méthode","owner":"58373e571cbccb010012bfcd"}],"nbFragments":1}]

您定义架构以使用owner填充fragments也称为虚拟人口。 http://mongoosejs.com/docs/populate.html

const userSchema =  new mongoose.Schema({
      email: { type: String, unique: true }
    }, { timestamps: true, collection: 'user' });

var User = mongoose.model("User", userSchema);

const fragmentSchema = new mongoose.Schema({
  text: String,
  owner: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
}, { timestamps: true, collection: 'fragment' });

var Fragment = mongoose.model("Fragment", fragmentSchema);

userSchema.virtual('fragments', {
    ref: 'Fragment',
    localField: '_id',
    foreignField: 'owner',
    options: { sort: { text: -1 }}, // Added sort just as an example
});

现在这将按预期工作,但我不知道如何对某些动态字段进行排序,例如猫鼬中片段数量的计数。我不认为这是可能的

User.find({_id: '58373e571cbccb010012bfcd'})
      .populate('fragments').exec(function (err, user) {
           console.log(JSON.stringify(user));
      });

现在好了动态排序,你必须使用$lookup(相当于populate)的替代原始mongo查询。

const userSchema =  new mongoose.Schema({
      email: { type: String, unique: true }
    }, { timestamps: true, collection: 'user' });

var User = mongoose.model("User", userSchema);

const fragmentSchema = new mongoose.Schema({
  text: String,
  owner: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
}, { timestamps: true, collection: 'fragment' });

User.aggregate([{
  $lookup: {
    from: 'fragment',
    localField: '_id',
    foreignField: 'owner',
    as: 'fragments'
  }
}, { "$project": {
  "email": 1,
  "fragments": 1,
  "nbFragments": {
    "$size": { "$ifNull": [ "$fragments", [] ] } }
}}, { "$sort": { "nbFragments": -1 } }
]).exec(function (err, user) {
       console.log(JSON.stringify(user));
})