0

messages私は以下の書類を集めています

{
  "_id" : ObjectId("5164218f359f109fd4000012"),
  "receiver_id" : ObjectId("5164211e359f109fd4000004"),
  "sender_id" : ObjectId("5162de8a359f10cbf700000c"),
  "body" : "Hello Billy!!!",
  "readed" : false,
  "updated_at" : ISODate("2013-04-09T14:11:27.17Z"),
  "created_at" : ISODate("2013-04-09T14:11:27.17Z")
}

特定のユーザー (reciever_id+sender_id フィールドでグループ化) の最後のメッセージを受信するためのクエリを作成する必要があります (受信または送信に関係なく)、created_at で並べ替えます。

質問をよりよく説明するために、SQLでどのように行ったかの例:

SELECT DISTINCT ON (sender_id+receiver_id) * FROM messages 
    ORDER by (sender_id+receiver_id), created_at DESC
    WHERE sender_id = given_user or receiver_id = given_user 

この問題をmondodbで解決する方法がわかりません。

4

2 に答える 2

2

MongoDB 2.2+のAggregation Frameworkは、クエリの最も明白な翻訳を提供します。MongoDB のマニュアルには、一般的なガイドとしてSQL から Aggregation Framework へのマッピング チャートが含まれていますが、2 つのアプローチには明確な違いがあります。

mongoシェルで試すことができるコメント付きの例を次に示します。

var given_user = ObjectId("5162de8a359f10cbf700000c");
db.messages.aggregate(
    // match: WHERE sender_id = given_user or receiver_id = given_user
    // NB: do the match first, because it can take advantage of an available index
    { $match: {
        $or:[
            { sender_id: given_user },
            { receiver_id: given_user },
        ]
    }},

    { $group: {
        //  DISTINCT ON (sender_id+receiver_id)
        _id: { sender_id: "$sender_id", receiver_id: "$receiver_id" }
    }},

    // ORDER by (sender_id+receiver_id), created_at DESC
    { $sort: {
        sender_id: 1,
        receiver_id: 1,
        created_at: -1
    }}
)

サンプル結果:

{
    "result" : [
        {
            "_id" : {
                "sender_id" : ObjectId("5162de8a359f10cbf700000c"),
                "receiver_id" : ObjectId("5164211e359f109fd4000004")
            }
        }
    ],
    "ok" : 1
}

受信したメッセージの数など、グループ化にフィールドを追加することができます。

実際に sender_id+receiver_id を 1 つのフィールドに結合したい場合は$concat、MongoDB 2.4+ で演算子を使用できます。

于 2013-04-09T15:41:53.233 に答える
1

これを行う明示的な方法はありません。回避策を確認しましょう。

方法 1: コード レベルで (検索後) 個別に実行し、次を使用しますfind

db.message.find({$or:[{sender_id:?}, {receiver_id:?}]})

方法 2: 集計フレームワークを使用する:

db.message.aggregate( [
   {$match: {$or:[{sender_id:?}, {receiver_id:?}]},
    $group: { _id: {sender:"$sender_id", receiver:"$receiver_id"},
               other: { ... } } },
   $sort: {sender_id,receiver_id,...}
   ] ) 

sender_id, receiver_id と同じではないため、この方法ではソートレベルで問題が発生しますsender_id+receiver_id

方法 3: サロゲート フィールド sender_id+receiver_id を導入し、Stennie ヒントごとにfindまたは使用します。distinct

于 2013-04-09T15:28:20.603 に答える