2016-09-06 1 views
2

(それは質問には重要なもののように簡略化)このようになります項目(マングース)スキーマがあります:

{ 
    brand: { 
     name: String, 
    }, 
    title: String, 
    description: [{ lang: String, text: String }], 
    shortDescription: [{ lang: String, text: String }], 
    variants: { 
     cnt: Number, 
     attrs: [ 
      { 
       displayType: String, 
       displayContent: String, 
       displayName: [{ lang: String, text: String }], 
       name: String, 
      }, 
     ], 
    } 
} 

私はアイテムをフィルタ処理しようとしています言語によって、私は次のクエリを構築しました:

db.items.aggregate([ 
    { $match: { 'description.lang': 'ca', 'shortDescription.lang': 'ca' } }, 
    { $project: { 
     'brand.name': 1, 
     title: 1, 
     description: { 
      '$filter': { 
       input: '$description', 
       as: 'description', 
       cond: { $eq: ['$$description.lang', 'ca'] } 
      } 
     }, 
     shortDescription: { 
      '$filter': { 
       input: '$shortDescription', 
       as: 'shortDescription', 
       cond: { $eq: ['$$shortDescription.lang', 'ca'] } 
      } 
     }, 
     'variants.cnt': 1, 
     'variants.attrs': 1 
    } } 
]) 

をそして、それは期待通りに動作します。それは、言語によってdescriptionshortDescriptionをフィルタリングします。今すぐすべてvariants.attrs.$.displayNameをフィルタリングすることが可能かどうか疑問に思っています。それを行う方法はありますか?

私は$unwindvariant.attrsにしようとしてきたが、再び$groupにしようとしたとき、私はcompletly迷子と私はこれが最善の方法であれば、本当にわからないんだけど...

+0

私は質問があります:description、shortDescription、variants.attrs variants.attrs.displayNameはリストです。これらの4つのリストはすべて複数の要素を持つことができますか? – sergiuz

+0

はい、すべての言語のテキストが含まれています。 'description:[{lang: 'en'、テキスト: 'This item is awful'}、{lang: 'es'、テキスト: 'Este producto esincreíble'}、...]' – Miquel

答えて

2

あなたはほとんどあります。これらの手順を試してみてください。

  • 文書の外側の配列を拡大する$project段階の前に使用$unwindステージ、すなわちvariants.attrs
  • $project段階でサブアレイvariants.attrs.displayNameのためのフィルタを追加します。
  • variantsキーのすべてのサブフィールドを投影する必要があります。
  • 次は、サブアレイを除くすべての要素で$groupステージとグループを追加します。グループごとにサブアレイを再構築するには、$pushを使用します。
  • 最後に、$projectステージを追加して、ドキュメントを元の構造に再構築します。

    db.items.aggregate([ 
        { $match: { 'description.lang': 'ca', 'shortDescription.lang': 'ca' } }, 
        { $unwind : "$variants.attrs" }, 
        { $project: { 
        '_id' : 1, 
        'brand.name': 1, 
        title: 1, 
        description: { 
         '$filter': { 
          input: '$description', 
          as: 'description', 
          cond: { $eq: ['$$description.lang', 'ca'] } 
         } 
        }, 
        shortDescription: { 
         '$filter': { 
          input: '$shortDescription', 
          as: 'shortDescription', 
          cond: { $eq: ['$$shortDescription.lang', 'ca'] } 
         } 
        }, 
        'variants.attrs.displayName' : { 
         '$filter' : { 
          input: '$variants.attrs.displayName', 
          as: 'variants_attrs_displayName', 
          cond: { $eq : ['$$variants_attrs_displayName.lang','ca']} 
         } 
         }, 
    
         'variants.cnt': 1, 
         'variants.attrs.displayType': 1, 
         'variants.attrs.displayContent' : 1, 
         'variants.attrs.name' : 1 
        } 
    } , { $group: 
          { 
          _id : { 
           _id: "$_id", 
           title: "$title", 
           brand:"$brand", 
           description:"$description", 
           shortDescription:"$shortDescription", 
           variants_cnt : "$variants.cnt" 
           }, 
          variants_attrs : { $push : 
          { 
           displayType : "$variants.attrs.displayType", 
           displayContent : "$variants.attrs.displayContent", 
           displayName : "$variants.attrs.displayName", 
           name: "$variants.attrs.name" 
          } 
          } 
         } 
        }, 
    { $project : 
    { 
        "_id" : 0, 
        brand : "$_id.brand", 
        title : "$_id.title", 
        description : "$_id.description", 
        shortDescription : "$_id.shortDescription", 
        variants : { 
         cnt : "$_id.variants_cnt" , 
         attrs : "$variants_attrs" 
        } 
        } 
    } 
    ]) 
    

あなたのユースケースに応じて、フィルタ値の重複を避けるために、あなたのdata model designを再考すべきです。すなわち、 'description.lang': 'ca'、 'shortDescription.lang': 'ca'、 'variants.attrs.displayName.lang': 'ca'

+0

これはソリューションの1つです。欠点は、モデルがローカライズされる前にモデルを知る必要があることです(標準化されていないためです)。最後に、私は 'ref'フィールドを持つソリューションを採用し、選択された言語でそれらを埋め込みました。この他のsolutinは、翻訳をフェッチするための追加の読み込みですが、スケーラビリティがあります。 – Miquel

関連する問題