1

Meteor を使用して簡単なメッセージング アプリを構築しています。未読メッセージで苦労しているセクション。ユーザー名を示すリストを返したいと思います(これについては気にしません。この側面、リアクティブ結合/コンポジットなどに焦点を当てないでください)およびそのユーザーからの最新のメッセージしたがっ て、返す必要があるもの、以下の発行機能では、最新の未読メッセージですが、明らかに各一意のユーザー ID から 1 つだけです。

これを行うには、公開メソッドで検索クエリの結果を操作しようとしていますが、現在以下のコードで示しているように、反応性を壊さずにドキュメント セットを操作する方法については不明です。私はこれまでのところ持っています:

Meteor.publish('unreadmessages', function() {

    if (!this.userId) {
        throw new Meteor.Error('denied', 'not-authorized');
    }

    var messageQuery, messages, userGroupQuery, userGroups;

    var self        = this;
    var user        = Meteor.users.findOne(self.userId);
    var userIdArr   = [self.userId]; // for use where queries require an array
    var contacts    = user.contacts;

    // get groups
    userGroupQuery  = Groups.find({
        $or : [
            { owner   : self.userId },
            { members : self.userId }
        ]
    }, { // Projection to only return the _id field
            fields : { _id:1 }
        }
    );

    userGroups = _.pluck(userGroupQuery.fetch(), '_id'); // create an array of id's

    messages = Messages.find({
        $or : [
            {
                $and : [
                    { participant : self.userId },
                    { userId : { $in : contacts } },
                    { readBy : { $nin : userIdArr } }
                ]
            },
            {
                $and : [
                    { groupId : { $in : userGroups } },
                    { readBy  : { $nin : userIdArr } }
                ]
            },
        ]
    });

     // TODO : also handle groups here
    uniqueMessages = _.uniq(messages.fetch(), function(msg) {
        return msg.userId;
    });

    return uniqueMessages; // obviously an array and not a cursor - meteor errors out.

});

私のアンダースコア関数はもちろん、必要なリアクティブカーソルではなく、配列を使用して実際に返していることに気付きました。1つの解決策は、単純にメッセージIDを取り出してからメッセージに対して別の.findを実行することであることは知っていますが、探している結果セットでカーソルを返す別の/より良い/より効率的/より自然な方法はありますか?

4

3 に答える 3

0

Heres the final working code. This does return a cursor as basically what I'm doing is taking the results from multiple queries / modifications and pumping a set of id's into the final .find query.

Meteor.publish('unreads', function() {
    if (!this.userId) {
        throw new Meteor.Error('denied', 'not-authorized');
    }

    // setup some vars
    var messageQuery,
        messages,
        userGroupQuery,
        userGroups,
        uniqeMsgIds;
    var self        = this;
    var user        = Meteor.users.findOne(self.userId);
    var userIdArr   = [self.userId]; // for use where queries require an array
    var contacts    = user.contacts;

    // get groups
    userGroupQuery  = Groups.find({
        $or : [
            { owner : self.userId },
            { members : self.userId }
        ]
    }, { // Projection to only return the _id field
            fields : { _id:1 }
        }
    );

    // create an array of group id's that belong to the user.
    userGroups = _.pluck(userGroupQuery.fetch(), '_id');

    messages = Messages.find({
        $or : [
            {  // unread direct messages
                $and : [
                    { participant : self.userId },
                    { userId : { $in : contacts } },
                    { readBy : { $nin : userIdArr } }
                ]
            },
            {  // unread group messages
                $and : [
                    { groupId : { $in : userGroups } },
                    { readBy : { $nin : userIdArr } }
                ]
            },
        ]
    }, { sort : { // put newest messages first
            time : -1
        }
    });

     // returns an array of unique documents based on userId or groupId
    uniqueMessages = _.uniq(messages.fetch(), function(msg) {
        if (msg.groupId) {
            return msg.groupId;
        }
        return msg.userId;
    });

    /*  Get the id's of all the latest unread messages
    (one per user or group) */
    uniqeMsgIds = _.pluck(uniqueMessages, '_id');

    /*  finally publish a reactive cursor containing
    one unread message(latest) for each user/group */
    return Messages.find({
        _id : { $in : uniqeMsgIds }
    });

});
于 2015-01-07T10:50:53.420 に答える