Mongoose - 获取与_id匹配的每个类别的最后一个

时间:2016-09-06 21:00:14

标签: mongodb mongoose

我有一个非常艰难的时间遇到​​一个我认为很容易的问题。我没有找到任何答案。我在Mongoose 4.5.4和MongoDb 2.2.2

我有一个看起来像这样的数据库(为了简单起见):

    [
        {
            _id:12547896
            category:1,
            state:1,
            member:256942158,
            laboratory:69547231,
            dt: 8-12-2015
        },
        {
            _id:11547528
            category:1,
            state:3,
            member:256942158,
            laboratory:69547231,
            dt: 21-12-2015
        },
        {
            _id:1554417
            category:2,
            state:2,
            member:256942158,
            laboratory:65827231,
            dt: 18-12-2015
        },
        {
            _id:11547528
            category:1,
            state:3,
            member:256942158,
            laboratory:69547231,
            dt:9-12-2015
        },
        {
            _id:1554417
            category:3,
            state:2,
            member:256942158,
            laboratory:65827231,
            dt: 9-12-2015
        }
     ]

我有3个类别。我想检索一个数组,其中包含匹配'成员'的每个类别的最后一个元素(一个用于类别1,另一个用于类别2等)。我尽量避免多次打电话,并尽可能学会干净使用猫鼬。

我试过这个:

    Collection.aggregate([
        {
            $unwind:'$category'
        },
        {
            $match:{
                member:data.id
            }
        },
        {
            $sort: {
                data: -1
            }
        },
        {
            $project: {
                _id:0,
                category:'$category',
                state:'$state',
                date:'$date'
            }
        },
        {
            $limit: 3
        }
        ],function(err,ts){
        console.log(ts);
    });

...但我没有得到每个类别中的一个。我得到以下内容:

    [
        {
            _id:12547896
            category:1,
            state:1,
            member:256942158,
            laboratory:69547231,
            dt: 8-12-2015
        },
        {
            _id:11547528
            category:1,
            state:3,
            member:256942158,
            laboratory:69547231,
            dt:9-12-2015
        },
        {
            _id:1554417
            category:3,
            state:2,
            member:256942158,
            laboratory:65827231,
            dt: 9-12-2015
        }
     ]

我做错了什么?我试着在网上找到的所有东西......请尽快!

2 个答案:

答案 0 :(得分:0)

这是答案。我不太确定,因为我只是在学习MongoDb和Mongoose。所以,如果你认为你可以改进答案,那就不要犹豫了。

基本上,我完全不在路上。我很想念$ unwind。另外,聚合不是获得我预期的正确方法。我想拥有最后一个'与该成员匹配的每个类别的项目。但目前还没有办法限制查询的答案只有最后一次。所以最后我决定对7个类别使用promises和chaine 7查询。

以下是架构:

var mongoose = require('mongoose');

var tsSchema = mongoose.Schema({
    ds:{
        type: Number,
        required: true
    },
    mb:{
        type: String,
        required: true
    },
    st:{
        type: Number,
        required: true
    },
    lb:{
        type: String,
        required: true
    },
    dt:{
        type: Date,
        default: Date.now
    },
    fb:{
        type: Boolean,
        default: false
    }
});

tsSchema.index({ mb: 1, dt: -1 });

var Ts = module.exports = mongoose.model('ts', tsSchema);

这是查询:

export default function loadStatus(req, err, models) {
    // extract the mongoose model I interested about. 
    var Ts = models.ts;
    var tot = [];
    // chaine 7 queries for the seven diseses
    return new Promise((resolve, reject) => {
        Ts
        .findOne({mb:req.body.id, fb:false, ds:0},{_id:1,ds:1,st:1,dt:1})
        .sort({dt:-1})
        .exec()
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 0,st: 0,dt: 0});
            }
            return Ts.findOne({mb:req.body.id, fb:false, ds:1},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1});
        })
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 1,st: 0,dt: 0});
            }
            return Ts.findOne({mb:req.body.id, fb:false, ds:2},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1});
        })
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 2,st: 0,dt: 0});
            }
            return Ts.findOne({mb:req.body.id, fb:false, ds:3},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1});
        })
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 3,st: 0,dt: 0});
            }
            return Ts.findOne({mb:req.body.id, fb:false, ds:4},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1});
        })
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 4,st: 0,dt: 0});
            }
            return Ts.findOne({mb:req.body.id, fb:false, ds:5},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1});
        })
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 5,st: 0,dt: 0});
            }
            return Ts.findOne({mb:req.body.id, fb:false, ds:6},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1});
        })
        .then(function(r){
            if(r){
                tot.push(r);
            }else{
                // if null, push default value
                tot.push({_id:0, ds: 6, fb:false, st: 0,dt: 0});
            }
            if(tot.length>0){
                resolve(tot);
            }else{
                reject('got a problem in the query chaine');
            }
        });
    });
}

重要! - >您将以这种方式进行弃用警告。你必须插入一个Promise Library。我选择了默认的ES6。为此,您必须添加一行调用Mongoose:

// connect at mongoDb datastore
var mongoURI = "mongodb://localhost/healthprover";
mongoose.Promise = global.Promise;
var db = mongoose.connect(mongoURI, function(err){
  if(err){
    console.log(err);
  }else{
    console.log('Finalmente sono connesso a Mongo!!!');
  }
});

我希望它可以帮助别人。欢呼声。

答案 1 :(得分:0)

我使用异步循环改进了我的查询。它更好。 : - )

export default function loadStatus(req, err, models) {
    // extract the mongoose model I interested about. 
    var Ts = models.ts;
    var Mb = models.members;
    var tot = [];
    var data = [];

    // prepare the function to retrieve the last update
    function asyncLoop( i, callback ) {
        if( i < 7 ) {
            // retrieve the values with the variable qr previously prepared
            Ts.findOne({mb:req.body.id, fb:false, ds:i},{_id:1,ds:1,st:1,dt:1}).sort({dt:-1}).exec(function(err,res)  {
                // if it exists, store the values in tot
                if(res){
                    tot.push(res);
                // if it doesn't exist, store a default value
                }else{
                    tot.push({_id:0, ds: i,st: 0,dt: 0});
                }
                asyncLoop( i+1, callback );
            })
        } else {
            callback();
        }
    }

    // first retrieve the data missing of the member selected
    return new Promise((resolve, reject) => {
        Mb.findOne({_id:req.body.id},{date:1,docnumber:1,email:1,phone:1}).exec()
        .then(function(member){
            if(member){
                // store the member data in a final variable
                data.push(member);
                // second, retrieve the las diseases correspondig to the member with an async loop
                asyncLoop(0, function(err){
                    data.push(tot);
                    if(data.length>0){
                        resolve(data);
                     }else{
                        reject('got a problem in the query chaine');
                     }
                });
            }
        });
    });
}