2014-10-17 2 views
1

Я пытаюсь рассчитать средний порядок заказа 2-го порядка моих клиентов.Mongo - Среднее значение второго документа

мне удастся сделать среднее количество 1-го порядка с помощью этого:

db.users.aggregate([ 
{$match: { 
    $and: [ 
     {$nor : [ { "emails.0.address" : "[email protected]" }, { "X.0.X" : "[email protected]" },{ "emails.0.address" : "[email protected]" },{ "emails.0.address" : "[email protected]" } ]}, 
     {orders: {$exists: true}} 
    ] 
}}, 
{$unwind: "$orders"}, 
{$group: { 
    _id: "$_id", 
    firstOrder: {$first: "$orders"} 
}}, 
{$group: { 
    _id: "$_id", 
    total: {$sum: "$firstOrder.total"} 
}}, 
{$group: { 
    _id: '', 
    average: {$avg: "$total"} 
}} 

])

Но это, кажется, немного по-другому, чтобы вычислить среднее количество 2-го порядка.

Я пытался работать с $Slice, но он не работает с aggregate и $Skip. Пропустите только первый заказ списка, но не в первом порядке каждого пользователя.

У вас есть какие-либо идеи по этому вопросу?

Большое спасибо за помощь. Ричард

ответ

0

Как вы в основном разработаны, не существует простой способ, чтобы получить в nth позиции массива. Но вы были на правильном пути, просто с немного большей обработкой и дополнительной настройкой. Поскольку вы не хотите быть обработки заказов, где нет второго порядка:

db.users.aggregate([ 

    // Match to make sure there is a second element, $and is actually implicit 
    { "$match": { 
     "$nor" : [ 
      { "emails.0.address" : "[email protected]" }, 
      { "X.0.X" : "[email protected]" }, 
      { "emails.0.address" : "[email protected]" }, 
      { "emails.0.address" : "[email protected]" } 
     ], 
     "orders.1": { "$exists": true } 
    }}, 

    // Then unwind to de-normalize 
    { "$unwind": "$orders"}, 

    // Keep the first order, and all the rest 
    { "$group": { 
     "_id": "$_id", 
     "firstOrder": { "$first": "$orders" } 
     "orders": { "$push": "$orders" } 
    }}, 

    // Yep, unwind again 
    { "$unwind": "$orders"}, 

    // Test to see the element that was already seen 
    { "$project": { 
     "orders": 1, 
     "matched": { "$eq": [ "$orders", "$firstOrder" ] } 
    }}, 

    // Filter out the matched element 
    { "$match": { "matched": false } }, 

    // Now the $first element is actually the "second" 
    { "$group": { 
     "_id": "$_id", 
     "secondOrder": { "$first": "$orders" } 
    }}, 

    // Summing is redundant, just average over all of it 
    { "$group": { 
     "_id": null, 
     "average": { "$avg": "$secondOrder.total" } 
    }} 
]) 

Так что очищает вещи немного, и получает вас среднее значение второго элемента, эффективно удаляя «первый» элемент из массив из конечных операций.

Если вы пропустили смысл ранее строку:

 "orders.1": { "$exists": true } 

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

+0

Поскольку ** orders ** - это массив, если второй элемент равен первому в некоторых документах, то некоторые из второго порядка будут потеряны ** выше согласованного **, что приведет к неправильному результату. – Wizard

+0

@Wizard Я надеюсь, что интеллигентные люди будут использовать уникальный идентификатор здесь. И поскольку нет никакого другого способа «срезать» массив в структуре агрегации, я не понимаю смысла вашей критики. У вас есть что-то умное предложить? Или ты просто ворчаешь, потому что сначала не думал об этом? –

+0

Я просто говорю о возможности. Я думаю, что любой вопрос и ответ открыты для обсуждения на stakoverflow. И люди могут ошибаться во время запроса или ответа, все возможно. Я удивлен, что мой комментарий делает вас несчастными. – Wizard

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