选择具有聚合的匹配数组

时间:2017-06-04 06:25:50

标签: mongodb mongodb-query aggregation-framework

hotdeal:

{ "property" : "ATL-D406" } 

翻译:

{ "property" : "ATL-D406", "language" : "gb", "txt": [{"aaa":"hi", "bbb":"bye"}] }
{ "property" : "ATL-D406", "language" : "ru", "txt": [{"aaa":"priviet", "bbb":"baka"}] } 
{ "property" : "ATL-D406", "language" : "cn", "txt": [{"aaa":"??", "bbb":"??"}] } 

目前的结果:

{ "property":"ATL-D406", "language":[ "gb", "ru", "cn" ] }

我想要的是什么:

{ "property":"ATL-D406", "language":"gb", "aaa":"hi", "bbb":"bye" }

我无法理解为什么我的$ elemMatch不起作用,不应该将结果中的特定元素与#34;翻译"?

分开

一旦我得到它只采取" gb"语言,我该如何投射" aaa"和" bbb"没有他们在阵列里面?我尝试了$ resolve,但后来我根本没有数据。你能解析数组中的数组吗? ($ resolve" txt")?

db.hotdeal.aggregate([ 
    { '$match': {} },
    { '$lookup': { 
        from: 'translation', 
        localField: 'property', 
        foreignField: 'property', 
        as: 'translations' 
    } },

    { '$match': 
        { 'translations': 
            { '$elemMatch': { 'language': 'gb' } }
        } 
    }, 

    { '$project': { 
        _id: 0, 
        property: 1, 
        language: '$translations.language'
    }}
])

2 个答案:

答案 0 :(得分:1)

你做错了手术。您希望$filter$map以及$arrayElemAt看起来如此。 $elemMatch运算符是"查询"操作"选择数据" ,并且不习惯于"过滤"数组内容。

db.hotdeal.aggregate([ 
    { '$match': {} },
    { '$lookup': { 
        'from': 'translation', 
        'localField': 'property', 
        'foreignField': 'property', 
        'as': 'translations' 
    } },
    { '$project': { 
        '_id': 0, 
        'property': 1, 
        'translation': {
         '$arrrayElemAt': [
           { '$map': {
             'input': {
               '$filter': {
                 'input': '$translations'
                 'as': 't',
                 'cond': { '$eq': [ '$$t.language', 'gb' ] }
               },
             },
             'as': 't',
             'in': {
               'language': '$$t',
               'aaa': { '$arrayElemAt': [ '$$t.txt.aaa', 0 ] },
               'bbb': { '$arrayElemAt': [ '$$t.txt.bbb', 0 ] }
             }
           }},
           0
         ]
       }
    }},
    { '$project': {
      'property': 1,
      'language': '$translation.language',
      'aaa': '$translation.aaa',
      'bbb': '$translation.bbb'
    }}
])

我通常会发现这些" trival" 结构更改最好在"客户端代码"而不是无论如何都要通过聚合框架。

所以简单地做"加入"然后让"客户"处理改动:

db.hotdeal.aggregate([ 
    { '$match': {} },
    { '$lookup': { 
        'from': 'translation', 
        'localField': 'property', 
        'foreignField': 'property', 
        'as': 'translations' 
    } }
]).forEach( doc => {
  let translation = doc.translations.find( t => t.language === 'gb' );
  doc.language = translation.language;
  doc.aaa = translation.txt[0].aaa;
  doc.bbb = translation.txt[0].bbb;

  delete doc.translations;
  delete doc._id;
  printjson(doc);
});

所以这是做同样的事情,但远不那么迟钝。

答案 1 :(得分:0)

db.hotdeal.aggregate([ 
    { '$match': {} },
    { '$lookup': { 
        from: 'translation', 
        localField: 'property', 
        foreignField: 'property', 
        as: 'translations' 
    } },

    { '$unwind': '$translations' },

    { '$match': { 'translations.language': 'gb' } }, 

    { '$project': { 
        _id: 0, 
        property: 1, 
        language: '$translations.language',
        aaa: '$translations.txt.aaa',
        bbb: '$translations.txt.bbb'
    }}
])