2013-05-08 7 views
1

Мои данные выглядит следующим образом:Почему MongoDB неверен?

{ 
     "_id":ObjectId("516fbf68067323ce2ea5b4b8"), 
     "title":"GVPKFlFIXdLUaLM", 
     "release_year":1913, 
     "country_of_origin":"sWdXLXUfun", 
     "length_in_minutes":147, 
     "plot_summary":"bmwYkyyiSymHJYoXEPauPNjdKoFANDgcDImVelDGPuPJmLhyWOuNXjurNyGp", 
     "director":"rNDFhhxGIo", 
     "language":"oYeWskT", 
     "popularity":5.2, 
     "genre":"jDwdaMhuT", 
     "actors":[ 
      { 
      "id":2740, 
      "name":"actor2740", 
      "dob":1989, 
      "alt_name":"PBpXPqJwmftpfcR", 
      "pob":"DFoxETDuhAdDGNE" 
      }, 
      { 
      "id":3143, 
      "name":"actor3143", 
      "dob":1953, 
      "alt_name":"AHnVvTviSKuvNZO", 
      "pob":"KBUdvbnvNkXmddk" 
      } 
     ] 
    } 

Сначала я думал, что ошибка в Монго. Я попытался решить гипотетическую бизнес-проблему, используя совокупную функцию. (Редактирование: Я не хочу сказать, что я решил проблему с Монго или что я хочу, чтобы люди, чтобы помочь мне создать алгоритм, только чтобы подтвердить потенциальную ошибку с MongoDB)

db.movies.aggregate([{$match:{popularity:{$gte:7.3}}}, 
    {$project:{actors:1,popularity:1}}, 
    {$unwind:"$actors"}, 
    {$group:{_id:"$actors.id",avgPop:{$avg:"$popularity"}, 
       docsByTag : { $sum : 1 }, popSum:{$sum:"$popularity"}}}, 
    {$match:{avgPop:{$gte:7.5}}}]); 

результата я сосредоточился на (редактировать $ sum: 1 not 0)

{ 
      "_id" : 1383, 
      "avgPop" : 8.772857142857141, 
      "docsByTag" : 28, 
      "popSum" : 245.63999999999996 
     }, 

Но когда я проверил результат вручную.

db.movies.find({"actors.name":"actor1383"},{title:1,popularity:1,_id: 0}) 

{ "title" : "kZFfBwtAfVNobEq", "popularity" : 8.54 } 
{ "title" : "kyOeSorYUWyJmjK", "popularity" : 8.11 } 
{ "title" : "rvSdJCgEkkpYgFB", "popularity" : 8.36 } 
{ "title" : "SwcgHTgZqqcYJja", "popularity" : 8.68 } 
{ "title" : "XmcidmdwtDlNoKw", "popularity" : 7.33 } 
{ "title" : "gwThvrWifoKCvyG", "popularity" : 7.94 } 
{ "title" : "RdUsAFIxTnntTZR", "popularity" : 6.91 } 
{ "title" : "RwhJlORFdvtDtpO", "popularity" : 5.13 } 
{ "title" : "TuDfcWhNkQFeycl", "popularity" : 9.93 } 
{ "title" : "xTVkwnyvftKQraC", "popularity" : 7.27 } 
{ "title" : "HYMjUFlSXgnWVTx", "popularity" : 6.94 } 
{ "title" : "ZPPyAUdGMeVQhbK", "popularity" : 8.48 } 
{ "title" : "kEITAiMMrWTECGM", "popularity" : 9.42 } 
{ "title" : "asNsLYKjvHlihXZ", "popularity" : 9.86 } 
{ "title" : "ctEmciXPhbMtspt", "popularity" : 8.85 } 
{ "title" : "DHjFtctccwDHtlf", "popularity" : 5.5 } 
{ "title" : "ElUqbLqkoKrJPVl", "popularity" : 8.26 } 
{ "title" : "XdTCieKsWtTbfZa", "popularity" : 5.72 } 
{ "title" : "EeNqOPSuKiHuWRs", "popularity" : 5.91 } 
{ "title" : "YgysqxcesvPryMY", "popularity" : 6.05 } 
{ "title" : "eARvpGydsWilquc", "popularity" : 7.34 } 
{ "title" : "NDpdkhSUfePDYjH", "popularity" : 7.28 } 
{ "title" : "wUGKLBwijftQKgU", "popularity" : 8.97 } 
{ "title" : "UHVGUmAcjBgAPBp", "popularity" : 7.44 } 
{ "title" : "NKTKEKfbxFrudVi", "popularity" : 9.4 } 
{ "title" : "AeByTKwsEQuQBYG", "popularity" : 8.97 } 
{ "title" : "nZskARfGbhYRxdY", "popularity" : 9.16 } 
{ "title" : "nBenZrikXFFrrnq", "popularity" : 7.58 } 
{ "title" : "GdEFwoKgqjhHvjM", "popularity" : 6.3 } 
{ "title" : "grpKTHgnYcDNyXH", "popularity" : 7.16 } 
{ "title" : "hXhOqknvjIYJIaT", "popularity" : 5.24 } 
{ "title" : "rggTJENnVeuqQVI", "popularity" : 9.95 } 
{ "title" : "ABvGVFHkgOumMPO", "popularity" : 9.56 } 
{ "title" : "baVkepHniIURUFH", "popularity" : 9.28 } 
{ "title" : "PUYXlhPwbanMDmT", "popularity" : 9.6 } 
{ "title" : "IJbqonvsVeorDMv", "popularity" : 7.82 } 
{ "title" : "iAhyATKYpCVjtMw", "popularity" : 5.88 } 
{ "title" : "uDECLFQGTOVnyvC", "popularity" : 6.25 } 
{ "title" : "rTwfCYLfLwgPcbH", "popularity" : 8.38 } 
{ "title" : "GRyKjecBHQhvYJk", "popularity" : 9.11 } 
{ "title" : "GyEaSHoprUvGmZM", "popularity" : 9.92 } 

который дает подмножество элементов 27 больше или равна 7,3

{ "title" : "kZFfBwtAfVNobEq", "popularity" : 8.54 } 
{ "title" : "kyOeSorYUWyJmjK", "popularity" : 8.11 } 
{ "title" : "rvSdJCgEkkpYgFB", "popularity" : 8.36 } 
{ "title" : "SwcgHTgZqqcYJja", "popularity" : 8.68 } 
{ "title" : "XmcidmdwtDlNoKw", "popularity" : 7.33 } 
{ "title" : "gwThvrWifoKCvyG", "popularity" : 7.94 } 
{ "title" : "TuDfcWhNkQFeycl", "popularity" : 9.93 } 
{ "title" : "ZPPyAUdGMeVQhbK", "popularity" : 8.48 } 
{ "title" : "kEITAiMMrWTECGM", "popularity" : 9.42 } 
{ "title" : "asNsLYKjvHlihXZ", "popularity" : 9.86 } 
{ "title" : "ctEmciXPhbMtspt", "popularity" : 8.85 } 
{ "title" : "ElUqbLqkoKrJPVl", "popularity" : 8.26 } 
{ "title" : "eARvpGydsWilquc", "popularity" : 7.34 } 
{ "title" : "wUGKLBwijftQKgU", "popularity" : 8.97 } 
{ "title" : "UHVGUmAcjBgAPBp", "popularity" : 7.44 } 
{ "title" : "NKTKEKfbxFrudVi", "popularity" : 9.4 } 
{ "title" : "AeByTKwsEQuQBYG", "popularity" : 8.97 } 
{ "title" : "nZskARfGbhYRxdY", "popularity" : 9.16 } 
{ "title" : "nBenZrikXFFrrnq", "popularity" : 7.58 } 
{ "title" : "rggTJENnVeuqQVI", "popularity" : 9.95 } 
{ "title" : "ABvGVFHkgOumMPO", "popularity" : 9.56 } 
{ "title" : "baVkepHniIURUFH", "popularity" : 9.28 } 
{ "title" : "PUYXlhPwbanMDmT", "popularity" : 9.6 } 
{ "title" : "IJbqonvsVeorDMv", "popularity" : 7.82 } 
{ "title" : "rTwfCYLfLwgPcbH", "popularity" : 8.38 } 
{ "title" : "GRyKjecBHQhvYJk", "popularity" : 9.11 } 
{ "title" : "GyEaSHoprUvGmZM", "popularity" : 9.92 } 

один меньше совокупной функции.

Так что я подумал, может быть заполнитель сломаны и переписал это как MapReduce

// make sure we're using the right db; this is the same as "use aggdb;" in shell 
db = db.getSiblingDB("recommendations"); //Put your MongoLab database name here. 



var mapFunc2 = function() { 
         for (var idx = 0; idx < this.actors.length; idx++) { 
          var key = this.actors[idx].id; 
          var value = { 
             count: 1, 
             pop: this.popularity 
             }; 
          emit(key, value); 
         } 
        }; 

var reduceFunc2 = function(keyActor, countObjVals) { 


        reducedVal = { actor: keyActor, count: 0, pop: 0, pop_list : [] }; 

        for (var idx = 0; idx < countObjVals.length; idx++) { 
         reducedVal.count += countObjVals[idx].count; 
         reducedVal.pop += countObjVals[idx].pop; 
         reducedVal.pop_list = reducedVal.pop_list.concat(countObjVals[idx].pop); 
        } 

        return reducedVal; 
        }; 

var finalizeFunc2 = function (key, reducedVal) { 

         reducedVal.avg = reducedVal.pop/reducedVal.count; 

         return reducedVal; 

        }; 


result = db.movies.mapReduce(mapFunc2, 
        reduceFunc2, 
        { 
         out: { merge: "mre" }, 
         query: { popularity: 
            { $gte: 7.3 } 
           }, 
         finalize: finalizeFunc2 
        } 
        ) 
cursor = db.map_reduce_example.find()     

while(cursor.hasNext()){ 
    printjson(cursor.next()); 

}

В результате снова выключен на один

{ 
    "_id" : 1383, 
    "value" : { 
     "actor" : 1383, 
     "count" : 28, 
     "pop" : 245.63999999999996, 
     "avg" : 8.772857142857141 
    } 
} 

Так что я начал отладки, и я вижу некоторые странные вещи, когда дело доходит до сохранения популярности каждого отдельного фильма в массиве.

{"_id": 1, "value": {"actor": 1, "count": 13, "pop": 114.97, "pop_list": [7.47, 8.52, 9.95, 17.4, 7.4, 19.43 , 8,46, 17,21, 9,24, 9,89], «средний»: +8,843846153846155}}

Вот, это странно, что отсчет 13, но число элементов равно 10. Это происходит из-за

7.4 7.4 
7.47 7.47 
8.07 1 
8.14 2 
8.46 8.46 
8.52 8.52 
9.14 1 
9.24 9.24 
9.26 2 
9.57 3 
9.86 3 
9.89 9.89 
9.95 9.95 

где 1,2,3 соответствуют

1 17.21=9.14+8.07 
2 17.4=8.14+9.26 
3 19.43=9.57+9.86 

{"_id": 2, "value": {"actor «: 2,« count »: 14,« pop »: 120.91999999999999,« pop_list »: [35.239999999999995, 7.58, 35.56, 9.35, 25.839999999999996, 7.35],« avg »: 8.637142857142857}} Однако вышеизложенное является полностью загадочным, поскольку все мои средние значения имеют только 2 десятичных знака.

Действительно смущенный в этой точке. Я уверен, что этот пост может быть полезен другим, которые застряли в том, что они видят одинаковые проблемы с подсчетом.

+0

Что вы пытаетесь считать? Вы начинаете говорить о решении, не указав свою проблему. –

+0

У вас есть ошибка cut-n-paste в вашей агрегации? Вы показываете {$ sum: 0}, и это дает 0. Используете ли вы последнюю версию? –

+0

Ася, спасибо, что выбрал {$ sum: 0}, это def. не то, что я хотел напечатать. Я показывал совокупность другу и случайно заменил 1 на 0. –

ответ

1

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

В ваших агрегациях вы группируетесь на поле "actors.id". Но ваш запрос, чтобы проверить вещи вручную является:

db.movies.find({"actors.name":"actor1383"},{title:1,popularity:1,_id: 0}) 

Есть ли доказательства того, что ваш «actors.name» и поле «actors.id» совпадают на 100%?

Точность выше 2 цифр является нормальной, когда вы выполняете арифметику с плавающей запятой и не о чем беспокоиться. Это ничем не отличается от запроса в среднем 5 и 10 и получения 7,5, хотя 5 и 10 у обоих не было цифр после десятичной точки.

Существует другое место, где может произойти «различие». Если у вас есть документ, как это:

{Популярность: 7.6, актеры: [ {ID: 1383, ... ... }, { ID: 1383, ... . .. }}

Теперь у вас есть только один документ верхнего уровня, что способствует, но когда вы разматывать массив актеров у вас есть два документа, которые являются результатом этого, когда оба actor.id 1383. Может вам убедитесь, что каждый актер появляется только один раз за документ верхнего уровня? Если это не приведет к несоответствию, которое вы видите.

+0

Ася, спасибо за ваш ответ. Давайте сосредоточимся на совокупности на секунду. Предполагается, что agg ({$ match: {popular: {$ gte: 7.3}}}) исключен из всех записей фильмов с поп ниже 7.3 Актер 1383 имеет 41 фильм: > db.runCommand ({count: 'movies' , запрос: {'actors.id': 1383, популярность: {$ gte: 0}}}) {"n": 41, "ok": 1} см. мое оригинальное сообщение для подробного вывода и теперь > db .runCommand ({count: 'movies', query: {'actors.id': 1383, популярность: {$ gte: 7.3}}}) {"n": 27, "ok": 1} Как можно это будет? И агрегация, и mapReduce дают значение 28. Это не имеет для меня никакого смысла. –

+0

Ася, просто для того, чтобы укрепить почему я думаю, что это ошибка в Монгоре, я повторил запрос db.movies.aggregate ([{$ project: {actors: 1, popular: 1}}, {$ unwind: "$ players"} , {$ group: {_ id: "$ actors.id", avgPop: {$ avg: "$ popular"}, docsByTag: {$ sum: 1}, popSum: {$ sum: "$ popular"}}}, {$ совпадение: {avgPop: {$ GTE: 0}}}]); И я взял матч перед проектом полностью. Но вы видите, что проблема все еще существует. Счет должен быть 41, но равен 42. И popSum выглядит действительно неправильно, потому что из-за точности. { \t \t \t "_id": 1383, \t \t \t "avgPop": +7,932857142857144, \t \t \t "docsByTag": 42, \t \t \t "popSum": +333,18000000000006 \t \t} –

+0

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

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