2015-10-05 8 views
5

私はこのようになりますメッセージのMongoのコレクションがあります。モンゴは、ソートの計算条件

{ 
    'recipients': [], 
    'unRead': [], 
    'content': 'Text' 
} 

受信者は、ユーザIDの配列で、未読はまだ開いていないすべてのユーザーの配列ですメッセージ。それは意図したとおりに働いて、私はそれが最初の20件の結果を返すように、すべてのメッセージのリストを照会する必要があり、最初の未読のものを優先、のようなもの:

db.messages.find({recipients: {$elemMatch: userID} }) 
    .sort({unRead: {$elemMatch: userID}}) 
    .limit(20) 

しかし、それは動作しません。特定の基準に合致するかどうかに基づいて結果の優先順位付けを行う最良の方法は何ですか?

答えて

5

結果を特定の基準で「重み付け」するか、「ソート」内に「計算値」を指定する場合は、代わりに.aggregate()メソッドが必要です。ここ

db.messages.aggregate([ 
    { "$match": { "messages": userId } }, 
    { "$project": { 
     "recipients": 1, 
     "unread": 1, 
     "content": 1, 
     "readYet": { 
      "$setIsSubset": [ [userId], "$unread" ] } 
     } 
    }}, 
    { "$sort": { "readYet": -1 } }, 
    { "$limit": 20 } 
]) 

$setIsSubsetオペレータが変換アレイと「未読」配列の比較を可能にする:これは、文書中にのみ存在するフィールドを使用することができるため$sort操作に使用する値を「投影」ことができ[userId]のいずれかが一致するかどうかを確認します。結果は、userIdが存在する場合はtrue、そうでない場合はfalseのいずれかになります。

これは、次いで、(一種であるtrue上降順)マッチに優先して検索結果を順序付けた、$sortに渡すことができ、最終的に$limitは単に指定された量までの結果を返します。

"ソート"の用語を使用するには、文書にソートされるように値をドキュメントに投影する必要があります。集約フレームワークは、これを行う方法です。

また、$elemMatchは、配列内の単一の値を照合するだけでは必要ではなく、値を直接指定する必要があります。その目的は、単一の配列要素で "複数の"条件を満たす必要がある場合ですが、ここでは当然当てはまりません。

+0

これは完全に機能しました。ありがとうございました!唯一のコメントは、$ setIsSubSetを$ setIsSubsetに変更するまでMongoがエラーを投げたことです。 – beatniknight

+0

@beatniknight典型的な私。ドキュメンテーションのリンクは正しかったですが、私のラクダの脳はそれが2つの言葉であると言い続け、それをそのようにタイプし続けます。 –