简体   繁体   中英

select collection and get the last item of each in other collection in MongoDB

I subscribed to the publication with the code below. So in my server side file,

Meteor.publish('people', function() {
    cursor = EmailDB.find({category:{$ne:"Spammer"}},{sort:{"lastMessage.date": -1},limit:20});
        let transformData = (fields) => {
                // this is the person we're processing now
                let eadd = fields.eadd;

                // get the latest message for this person
                key.eadd = eadd;
                let lastMessage = MessageDB.findOne(key,
                    {
                        sort: {date: -1}
                    }
                );

                // add his last message to the returned data
                fields.lastMessage = lastMessage;

                return fields;
            };

            let handle = cursor.observeChanges({
                added: (id, fields) => {
                fields = transformData(fields);
            this.added('emails', id, fields);
        },
            changed: (id, fields) => {
                fields = transformData(fields);
                this.changed('emails', id, fields);
            },
            removed: (id) => {
                this.removed('emails', id);
            }
        });

            this.ready();

            this.onStop(() => {
                handle.stop();
        });
        return cursor;
}

It get all the records of Person. I want to get the latest message of each person. So I used the code above but it is not working, It does not add additional fields to my query.

I need to just subscribe and fetch all records, and in each record there must be a last message.

whenever you want to join data from 2 published collections like this, you have a choice of doing it on the client or on the server. if you do it on the client, you've created a race condition for yourself. it can be solved, but i find it's cleaner and easier to do it on the server. and it makes it dead simple on the client, since you need to subscribe to only one collection.

so to do it on the server, you can take care of it in the publish. there, you can transform a returned collection (PersonDB) and add data to it (MessagesDB).

i don't know what your collections look like, or how they're named, so i'm obviously making some assumptions here.

Meteor.publish('people', function() {
    let cursor = PersonDB.find({});

    let transformData = (fields) => {
        // this is the person we're processing now
        let personId = fields.personId;

        // get the latest message for this person
        let lastMessage = MessagesDB.findOne({personId: personId},
            {
                sort: {createdAt: -1}
            }
        );

        // add his last message to the returned data
        fields.lastMessage = lastMessage;

        return fields;
    };

    let handle = cursor.observeChanges({
        added: (id, fields) => {
            fields = transformData(fields);
            this.added('personsdb', id, fields);
        },
        changed: (id, fields) => {
            fields = transformData(fields);
            this.changed('personsdb', id, fields);
        },
        removed: (id) => {
            this.removed('personsdb', id);
        }
    });

    this.ready();

    this.onStop(() => {
        handle.stop();
    });
});

on the client, you can subscribe to PersonDB like normal, and do the find like normal, and on each record you'll now have a "lastMessage" field appended.

您需要在MessagesDB中添加PersonDB ID(如果不是这种情况)

MessagesDB.find({PersonDB:PersonDB._id},{limit:1}).fetch()[0]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM