2016-02-22 3 views
2

У меня есть документы, как:Монго Group и сумма с двумя полями

{ 
    "from":"[email protected]", 
    "to" :"[email protected]", 
    "email": "Hi hello" 
} 

Как мы можем вычислить подсчет суммы «от и до» или «и из»? Как связь между двумя людьми?

Я могу рассчитать сумму в один конец. Я хочу иметь сумму в обоих направлениях.

db.test.aggregate([ 
     { $group: { 
     "_id":{ "from": "$from", "to":"$to"}, 
      "count":{$sum:1} 
     } 
     }, 
     { 
     "$sort" :{"count":-1} 
     } 
]) 
+0

Я думаю, что вы уже учли сумму в оба конца. результат может понравиться belows: {_id: {from: "a", to: "b"}, count 100} {_id: {from: "b", to: "a"}, count: 1000}, в обоих направлениях результаты выводятся. – zydcom

+0

@zydcom: Нет, нет. –

ответ

2

Поскольку вам нужно вычислить количество писем обменены между 2 адреса, было бы справедливо, чтобы проект единого between поля следующим образом:

db.a.aggregate([ 
    { $match: { 
     to: { $exists: true }, 
     from: { $exists: true }, 
     email: { $exists: true } 
    }}, 
    { $project: { 
     between: { $cond: { 
      if: { $lte: [ { $strcasecmp: [ "$to", "$from" ] }, 0 ] }, 
      then: [ { $toLower: "$to" }, { $toLower: "$from" } ], 
      else: [ { $toLower: "$from" }, { $toLower: "$to" } ] } 
     } 
    }}, 
    { $group: { 
     "_id": "$between", 
     "count": { $sum: 1 } 
    }}, 
    { $sort :{ count: -1 } } 
]) 

Унификация логика должна быть совершенно ясно из Например: это отсортированный по алфавиту массив обоих писем. Части $match и $toLower являются необязательными, если вы доверяете своим данным.

документации для операторов, используемых в данном примере:

+0

Можете ли вы объяснить, что вы подразумеваете под '$ cond'? –

+0

Я сомневаюсь, что я могу объяснить это лучше, чем в документах. Я добавил ссылки, если это поможет. –

+0

Я знаю $ cond, я хотел понять, какую логику вы там сделали. –

3

Вы в основном нужно учитывать _id для группировки, как "массив" возможного "до" и "от" значений, а затем конечно, «сортировать» их, так что в каждом документе комбинация всегда находится в одном порядке.

Как примечание, я хочу добавить, что «обычно», когда я имею дело с системами обмена сообщениями, как это, отправители/получатели «от» и «от» обычно являются как массивами для начала, так и обычно образует основу, из которой исходят разные вариации этого утверждения.

Во-первых, наиболее оптимальным MongoDB 3.2 утверждение, для отдельных адресов

db.collection.aggregate([ 
    // Join in array 
    { "$project": { 
     "people": [ "$to", "$from" ], 
    }}, 

    // Unwind array 
    { "$unwind": "$people" }, 

    // Sort array 
    { "$sort": { "_id": 1, "people": 1 } }, 

    // Group document 
    { "$group": { 
     "_id": "$_id", 
     "people": { "$push": "$people" } 
    }}, 

    // Group people and count 
    { "$group": { 
     "_id": "$people", 
     "count": { "$sum": 1 } 
    }} 
]); 

Вот основы, а теперь только вариации в строительстве «люди» массива (стадия 1 только выше).

MongoDB 3.x и 2.6.x - Массивы

{ "$project": { 
    "people": { "$setUnion": [ "$to", "$from" ] } 
}} 

MongoDB 3.x и 2.6.x - Поля для массива

{ "$project": { 
    "people": { 
     "$map": { 
      "input": ["A","B"], 
      "as": "el", 
      "in": { 
       "$cond": [ 
        { "$eq": [ "A", "$$el" ] }, 
        "$to", 
        "$from" 
       ] 
      } 
     } 
    } 
}} 

MongoDB 2.4.x и 2.2.х - от полея

{ "$project": { 
    "to": 1, 
    "from": 1, 
    "type": { "$const": [ "A", "B" ] } 
}}, 
{ "$unwind": "$type" }, 
{ "$group": { 
    "_id": "$_id", 
    "people": { 
     "$addToSet": { 
      "$cond": [ 
       { "$eq": [ "$type", "A" ] }, 
       "$to", 
       "$from" 
      ] 
     } 
    } 
}} 

Но во всех случаях:

  1. Получить все получатель в отдельный массив.

  2. Заказывайте массив последовательного порядка

  3. группы по «всегда в том же порядке» список получателей.

Следуйте за этим, и вы не ошибетесь.

Смежные вопросы