JMA JMA - 1 year ago 78
React JSX Question

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.

zim zim
Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download