2017-01-04 3 views
1

ゲームで50人のメンバーのデータに続いて1日に1回APIをヒットし、mongooseを使用してJSONをコレクションの個々のドキュメントに変換します。日々の間に、例えば各メンバーのタグ(ゲーム内のメンバーのID)が異なるが、異なるデータ(異なるスコアなど)があるなど、一貫性のあるデータがある。各ドキュメントにはcreatedAtというプロパティがあります。

各メンバーの最新のドキュメントを探したいので、各メンバーのタグ付きの配列があります。

私は現在、タグが一致するすべてのドキュメントを見つけるために次のクエリを使用していますが、すべてのドキュメントを返しています。どのように私は並べ替え/最新の1つにクエリを(またはより多くの "mongodbの方法"です)を維持しながら、ドキュメントを制限するのですか?

memberTags = [1,2,3,4,5]; 
ClanMember.find({ 
    'tag': { 
     $in: memberTags 
    } 
}).lean().exec(function(err, members) { 
    res.json(members); 
}); 

おかげ

+0

は、集約を介して行うことができます。 –

答えて

1

集約フレームワークを使用して照会することができます。クエリには、pipelineが含まれ、入力文書を処理して所望の結果を得る段階があります。あなたのケースでは、パイプラインは$matchフェーズを持ち、初期フィルタのクエリとして機能します。 $matchは標準のMongoDBクエリを使用するため、依然として$inを使用してクエリできます。

次の手順は、フィルタリングされたドキュメントをcreatedAtフィールドでソートすることです。これは、$sortの演算子を使用して行われます。

上記のパイプラインステージでは、順序付けされたドキュメントを集約して、各グループの先頭のドキュメントを返します。 $group演算子と$firstアキュムレータは、これを可能にする演算子です。完全にあなたが希望する結果を取得するには、以下の集約演算を実行することができ、これを置く

memberTags = [1,2,3,4,5]; 
ClanMember.aggregate([ 
    { "$match": { "tag": { "$in": memberTags } } }, 
    { "$sort": { "tag": 1, "createdAt: -1 " } }, 
    { 
     "$group": { 
      "_id": "$tag", 
      "createdAt": { "$first": "$createdAt" } /*, 
      include other necessary fields as appropriate 
      using the $first operator e.g. 
      "otherField1": { "$first": "$otherField1" }, 
      "otherField2": { "$first": "$otherField2" }, 
      ... 

      */ 
     } 
    } 
]).exec(function(err, members) { 
    res.json(members); 
}); 

それとも2つのフィールドで並べ替えることができるようにfind()を使用して現在のクエリを微調整は、(tag、すなわち昇順)およびcreatedAt(降順)属性です。その後、制限、次のようなものを使用して、トップ5の文書を選択することができます。

memberTags = [1,2,3,4,5]; 
ClanMember.find(
    { 'tag': { $in: memberTags } }, // query 
    {}, // projection 
    { // options 
     sort: { 'createdAt': -1, 'tag': 1 }, 
     limit: memberTags.length, 
     skip: 0 
    } 
).lean().exec(function(err, members) { 
    res.json(members); 
}); 

または

memberTags = [1,2,3,4,5]; 
ClanMember.find({ 
    'tag': { 
     $in: memberTags 
    } 
}).sort('-createdAt tag') 
    .limit(memberTags.length) 
    .lean() 
    .exec(function(err, members) { 
    res.json(members); 
}); 
+0

素晴らしいですが、 'aggregate'クエリはうまくいきましたが、' find() 'クエリを微調整してもうまくいきましたが、クエリに必要なフィールドを繰り返す必要はありませんでした。ありがとうございました! – GarethPrice

+0

心配しなくてもうれしいです。当初は、「集約」アプローチしか考えられませんでしたが、いくつかのことを考えすぎる必要はありません。 – chridam

1

オクラホマので、まずは、findOne()を使ってみましょうあなたはその後、最新の文書でソートする要求 のうちの1つの文書のみを取得するので、あなたが.sort({elementYouWantToSort: -1})を使用することができます(-1あなたが望む意味古いものから最も古い、そして1にnewestからソートする) 私はすでに私たちに次のリクエストを与える文書 の作成日を含む_id、上でこの機能を使用することをお勧めします:

ClanMember.findOne({ 
    'tag': { 
     $in: memberTags 
    } 
}).sort({_id: -1}).lean().exec(function(err, members) { 
    res.json(members); 
}); 
+0

各タグの最新のドキュメントではなく、1つのドキュメントだけを返しますか? – GarethPrice