2017-01-24 4 views
0

私は以下のようなテーブル構造を持っています。既存の文書または新しく追加された文書の入手方法

{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6b8"), 
"product" : "product1", 
"title" : "Alt Summit 1", 
"category" : "category1", 
"order" : 1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6b9"), 
"product" : "product2", 
"title" : "Alt Summit 2", 
"category" : "category1", 
"order" : 2 
} 
    { 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6ba"), 
"product" : "product1", 
"title" : "Alt Summit 1", 
"category" : "category1", 
"order" : 2, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bb"), 
"product" : "product2", 
"title" : "Alt Summit 2", 
"category" : "category1", 
"order" : 1, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bc"), 
"product" : "product3", 
"title" : "Alt Summit 3", 
"category" : "category1", 
"order" : 3, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bd"), 
"product" : "product4", 
"title" : "Alt Summit 4", 
"category" : "category1", 
"order" : 4 
} 

まず、データベース構造について説明します。

ウェブサイトのすべてのユーザーにデフォルトの製品があり、ユーザーは自分の製品をリストに追加することも、既存のリストを並べ替えることもできます。彼らが新しい製品を追加すると、ユーザー名で追加されます。彼らが商品を再注文するとき、私は既存のデフォルトレコードを取得し、ユーザー名を追加して挿入し、注文を変更します(上記のデータを守っていただければ分かります)。

ここで、ユーザー固有のカテゴリの製品を入手するにはどうすればよいですか。

たとえば、カテゴリ1のuser1のすべての商品を取得する必要がある場合、出力は次のようになります(注文フィールドに基づいてソートされます)。上記のデータを慎重に守っていただいた場合は、add_byという名前の追加フィールドが追加され、注文が変更された同じ製品が繰り返されます。私はユーザーがそれをカスタマイズした場合、ユーザーの注文を取得したい、デフォルトの注文ではない。

{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bb"), 
"product" : "product2", 
"title" : "Alt Summit 2", 
"category" : "category1", 
"order" : 1, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6ba"), 
"product" : "product1", 
"title" : "Alt Summit 1", 
"category" : "category1", 
"order" : 2, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bc"), 
"product" : "product3", 
"title" : "Alt Summit 3", 
"category" : "category1", 
"order" : 3, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bd"), 
"product" : "product4", 
"title" : "Alt Summit 4", 
"category" : "category1", 
"order" : 4 
} 

私はテーブルの構造を変更する必要がある場合には、何か提案がありますか?しかし、いつでも私は上記の出力に到達することができます。

+0

'db.yourCollection.find({ "カテゴリー": "カテゴリ1"、 "added_by": "USER1"})。ソート({ "オーダー":1})'あなた」にカーソルを返す必要があります探していますか? – Adam

+0

いいえ@Adamユーザーがオブジェクトの順序を変更していない場合でも、デフォルトの製品を取得する必要があります。上記のクエリでは、ユーザーが追加した製品またはユーザーが再注文した製品のみが表示されます。デフォルトで同じカテゴリの同じ商品がユーザーによって追加されている場合は、他のデフォルト商品と一緒にユーザー注文を取得する必要があります。 – Shravya

+0

デフォルトの製品は '' added_by "'キーを持たないものとして定義されていますか?その場合は、 'db.yourCollection.find({" $または ":{category": "category1"、 "added_by": "user1"}、{"added_by":{"$ exists":false} }]})。sort({"order":1}) ' – Adam

答えて

1

現在のMongo 3.4バージョンでは、以下の集計を試すことができます。

$matchクエリ基準のドキュメント。 product$$ROOTで文書を維持しながら、以前のソート順に基づいて$firstを選ぶ上

$group文書。

$replaceRootrootドキュメントをトップレベルに昇格させる。

'$ sort' by orderフィールド。

db.collection.aggregate([{ 
    $match: { 
    "category": "category1", 
     $or: [{ 
      "added_by": "user1" 
     }, { 
      "added_by": { 
       "$exists": false 
      } 
     }] 
    } 
}, { 
    $group: { 
     "_id": "$product", 
     "root": { 
      "$first": "$$ROOT" 
     } 
    } 
}, { 
    $replaceRoot: { 
     newRoot: "$root" 
    } 
},{ 
    $sort: { 
     "order": 1 
    } 
}]) 

更新OPのコメントの後にproduct

$group文書や$$ROOT$pushすべての製品。ない$eq$filter次いで1〜場合added_byフィールドに製品を選択する$sizeを比較する

$project段階。

db.collection.aggregate([{ 
    $match: { 
     "category": "category1", 
     $or: [{ 
      "added_by": "user1" 
     }, { 
      "added_by": { 
       "$exists": false 
      } 
     }] 
    } 
}, { 
    $group: { 
     "_id": "$product", 
     "products": { 
      "$push": "$$ROOT" 
     } 
    } 
}, { 
    $project: { 
     "_id": 0, 
     "product": { 
      "$arrayElemAt": [{ 
        "$cond": [ 
         { 
          $eq: [{$size: "$products"}, 1] 
         }, 
         "$products", 
         { 
          "$filter": { 
           input: "$products", 
           as: "product", 
           cond: { 
            $ifNull: ["$$product.added_by", false] 
           } 
          } 
         } 
        ] 
       }, 
       0 
      ] 
     } 
    } 
}, { 
    $replaceRoot: { 
     newRoot: "$product" 
    } 
}, { 
    $sort: { 
     "order": 1 
    } 
}]); 
+0

@Veeramさんへのお返事ありがとうございます。私はあなたが2つのうちの最初の文書を選んでいるのを見ます。しかし、最初の要素または最後の要素を選択する代わりに、added_byフィールドを持つ文書を選択する方法はありますか?私はあなたが与えた解決策をまだ投稿した構造についてはまだ良いと思う。私はとにかくそれをチェックするつもりですが、あなたがこのコメントで言及した変更を更新することができれば素晴らしいと思います。 – Shravya

+0

ようこそ。私は答えを更新しますが、ちょっとだけ理解する必要があります。私は間違いを犯したと思うし、最後の製品を選んだはずです。最後の商品を注文した理由は、デフォルト商品の注文後に商品の注文を再注文すると考えたからです。だからパイプラインで並べ替えることで、私は最後に注文商品を持っていきます。そうじゃないの?ユーザーは注文を選択できますか? – Veeram

+0

ほとんどのケースでは、最後の製品を選択する必要があります。しかし、私はあなたが以前に聞いたことのない全く異なるシナリオを持っていると思います。注文が何であるかを確認するカテゴリ内のユーザーによって商品が追加された場合、商品を選択したいと考えています。そのような場合には、製品を再注文するだけでなく、そのカテゴリに製品を追加することもできるので、デフォルト製品がユーザーによって追加された同じ製品の前または後にある可能性があります。だから、この作品を作るために、私はそれが最初または最後に基づいていないが、私はユーザーの製品を追加する前に、または既定の製品の後にすることができますしたい。 – Shravya

関連する問題