1

Web サイトのメッセージング受信トレイをセットアップしようとしていますが、ユーザー (送信者または受信者) のすべてのドキュメントをスレッドにグループ化する必要があります。メッセージ コレクションは、次のようなドキュメントでいっぱいです。

{
"_id" : ObjectId("4fe8d8ac0a6d2ad9350000d9"),
"message" : "booo",
"recipient" : {
    "user_id" : ObjectId("4fd9f0600a6d2ac94f000003"),
    "viewed" : 1
},
"sender" : {
    "user_id" : ObjectId("4fdb3b780a6d2a9d29000047"),
},
"thread" : "c03a4e49348d009f4ddd8aae325128e1"
"date_sent" : ISODate("2012-06-25T21:31:24.230Z"),

}

mongo のグループ関数を使用して目的の結果を得ることができますが、グループで並べ替えや制限を行うことはできないため、理想的には集計フレームワークを使用したいのですが、目的の結果を得るのに問題があります。基本的に私はこれを行う必要があります:

    $groupBy = array(
            'thread'    =>  1,
        );
    $initial = array('count' => 0);

    $reduce = "function (obj, prev) { 
            prev.count++; 
            prev.message = obj.message; 
            prev.sender = obj.sender.user_id;
            prev.recipient = obj.recipient.user_id;
            prev.date_sent = obj.date_sent;
            prev.viewed = obj.recipient.viewed;
        }";

    $condition = array(
            '$or' => array(
                            array('sender.user_id'      => new MongoId($options['user_id'])), 
                            array('recipient.user_id'   => new MongoId($options['user_id']))
                        )
        );
    return $this->_collection->group($groupBy, $initial, $reduce, $condition);

集計フレームワークを使用していますが、必要な結果が得られません...基本的に私はこれを持っています:

    $condition = array(
            '$or' => array(
                            array('sender.user_id'      => new MongoId($options['user_id'])), 
                            array('recipient.user_id'   => new MongoId($options['user_id']))
                        )
        );
    $returnFields = array(
            'message'           =>  1,
            'sender.user_id'    =>  1,
            'recipient.user_id' =>  1,
            'date_sent'         =>  1,
            'thread'            =>  1,
        );
    $sort       = array('date_sent' =>  1);
    $groupBy    = array('_id'       =>  '$thread');

    $input = array(
        'aggregate' =>  $this->_collectionName,
        'pipeline'  =>  array(
                array('$project'  =>  $returnFields),
                array('$match'    =>  $condition),
                array('$group'    =>  $groupBy),
                array('$sort'     =>  $sort),
            )
    );
    return $this->_db->command($input);

そして、それは私の $project を無視しているように、スレッドを返すだけです...何か考えはありますか?

4

1 に答える 1

0

私はそれを理解しました。$project が実行されない理由はよくわかりませんが、 $first 演算子を使用して $group ステートメントのフィールドを選択できます

    $condition = array(
            '$or' => array(
                            array('sender.user_id'      => new MongoId($options['user_id'])), 
                            array('recipient.user_id'   => new MongoId($options['user_id']))
                        )
        );

    $sort       = array('date_sent' =>  -1);

    $groupBy    = array(
            '_id'       =>  '$thread',
            'sender'    =>  array('$first' => '$sender.user_id'),
            'recipient' =>  array('$first' => '$recipient.user_id'),
            'date_sent' =>  array('$first' => '$date_sent'),
            'message'   =>  array('$first' => '$message'),
            'viewed'    =>  array('$first' => '$recipient.viewed'),
        );

    $input = array(
        'aggregate' =>  $this->_collectionName,
        'pipeline'  =>  array(
                array('$match'    =>  $condition),
                array('$sort'     =>  $sort),
                array('$group'    =>  $groupBy),
                array('$sort'     =>  $sort),

            )
    );

    return $this->_db->command($input);

基本的には、適切なドキュメントを照合し、最新のメッセージが最初になるように並べ替え、$group を実行して、$first 演算子でフィールドを選択し、再度並べ替えて、正しい順序になるようにする必要があります。それが必要になるとは思いませんでしたが、これは正しく機能しているようです。

于 2012-06-26T22:30:25.360 に答える