2014-08-29 2 views
0

Я пытаюсь создать совокупность наиболее просматриваемого элемента (авторов).

Вот моя коллекция пользователей:

{ 
    "_id" : ObjectId("54008ac8145a6cc5058b456b"), 
    "history" : { 
    "authors" : [ 
     { 
     "name" : "michou", 
     "count" : { 
      "all" : NumberLong(1), 
      "2014" : NumberLong(1), 
      "201408" : NumberLong(1), 
      "2014w35" : NumberLong(1) 
     } 
     } 
    ] 
    } 
} 
{ 
    "_id" : ObjectId("54008ac8145a6ccb058b4570"), 
    "history" : { 
    "authors" : [ 
     { 
     "name" : "petitBonhommeEnMousse", 
     "count" : { 
      "all" : NumberLong(2), 
      "2014" : NumberLong(2), 
      "201408" : NumberLong(2), 
      "2014w35" : NumberLong(2) 
     } 
     }, 
     { 
     "name" : "lordVador", 
     "count" : { 
      "all" : NumberLong(1), 
      "2014" : NumberLong(1), 
      "201408" : NumberLong(1), 
      "2014w35" : NumberLong(1) 
     } 
     } 
    ] 
    } 
} 
{ 
    "_id" : ObjectId("54008ac8145a6ccf058b456c"), 
    "history" : { 
    "authors" : [ 
     { 
     "name" : "lordVador", 
     "count" : { 
      "all" : NumberLong(1), 
      "2014" : NumberLong(1), 
      "201408" : NumberLong(1), 
      "2014w35" : NumberLong(1) 
     } 
     } 
    ] 
    } 
} 

То, что я хотел бы получить список количества времени, которое пользователь видел автор в течение последних трех недель.

Для этого, когда пользователь видит страницу, я увеличиваю значение ключа «2014w35», «2014w36» ... (номер недели в году).

Вот первая попытка:

db.users.aggregate(
    [ 
    { $match: { history_updated: "20140829" } }, 
    { $unwind: "$history.authors" }, 
    { $group : 
     { 
     "_id" : "$history.authors.name", 
     "total2014w35" : {"$sum" : "$history.authors.count.2014w35"}, 
     "total2014w34" : {"$sum" : "$history.authors.count.2014w34"}, 
     "total2014w33" : {"$sum" : "$history.authors.count.2014w33"} 
     } 
    }, 
    { $project: { 
     "_id" : 1, 
     "total" : { 
      $add : [ 
      "$total2014w35", 
      "$total2014w34", 
      "$total2014w33" 
      ] 
     } 
     } 
    } 
    ] 
) 

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

{ "_id" : "lordVador", "total" : NumberLong(2) } 
{ "_id" : "petitBonhommeEnMousse", "total" : NumberLong(2) } 
{ "_id" : "michou", "total" : NumberLong(1) } 

Моя вторая attemps была группе _id:

db.users.aggregate(
    [ 
    { $match: { history_updated: "20140829" } }, 
    { $unwind: "$history.authors" }, 
    { 
     $group : 
     { 
     "_id" : "$_id", 
     .... 

Что, конечно, возвращает общее число авторов просмотра пользователем. Но без автора.

{ "_id" : ObjectId("54008ac8145a6ccb058b4570"), "total" : NumberLong(3) } 
{ "_id" : ObjectId("54008ac8145a6ccf058b456c"), "total" : NumberLong(1) } 
{ "_id" : ObjectId("54008ac8145a6cc5058b456b"), "total" : NumberLong(1) } 

То, что я хотел бы иметь представляет собой смесь обоих. Я хотел бы иметь для каждого пользователя (документ в коллекции) список авторов, для каждого, сколько раз пользователь видел его/ее, в течение последних 3 недель.

Что-то вроде:

{ "_id" : ObjectId("54008ac8145a6ccb058b4570"), [{ "lordVador" : NumberLong(3) },{ "michou" : NumberLong(1) } ] } 
{ "_id" : ObjectId("54008ac8145a6ccf058b456c"), [{ "petitBonhommeEnMousse" : NumberLong(1) } ] } 
{ "_id" : ObjectId("54008ac8145a6cc5058b456b"), [{ "lordVador" : NumberLong(1) } ] } 

У кого из вас есть какие-либо идеи, как их смешивать?

+0

Я не понимаю, что вам нужно. Пожалуйста, объясните более четко. Что такое пользователь? Каждый из документов, которые вы приводите в качестве примеров, представляет пользователя? В этом случае, похоже, информация, которую вы хотите, в значительной степени находится только в оригинальном документе. Каковы странные ключи, такие как «2014w35»? Почему вы (по-видимому) используете значения в качестве ключей? Почему вы не используете даты? – wdberkeley

+0

Привет, извините, если не ясно. Я обновил свой вопрос. Да, каждый документ в коллекции является одним пользователем. Я хотел бы иметь для каждого пользователя (документ в коллекции) список авторов, для каждого, сколько раз пользователь видел его/ее, в течение последних 3 недель. 2014w35 представляют 35-ю неделю 2014 года. Я не использовал даты, потому что я хранил их по неделям. –

ответ

1

Используя рамки Aggregation, вы не можете получить карту между именами авторов и их подсчетов. В лучшем случае вы можете получить, это две разные массивы считаются ассоциативными:

db.user.aggregate([ 
{$match: {"history_updated": "20140829" } }, 
{$unwind:"$history.authors"}, 
{$group:{"_id":"$_id","authors":{$push:"$history.authors.name"}, 
     "visits_last_three_mnths":{$push:{$add:["$history.authors.count.201408","$history.authors.count.2014w35"]}}} 
} 
]) 

образца о/р: (изменили идентификаторы, числа, удалили пользователя из вашего примера)

{ "_id" : 2, "authors" : [ "petitBonhommeEnMousse", "lordVador" ], "visits_last_three_mnths" : [75,150 ] } 
{ "_id" : 1, "authors" : [ "michou" ], "visits_last_three_mnths" : [ 300 ] } 

Примечание: Ассоциативность сохраняется в соответствии с их индексами в числе «авторов» и массивов «посещения_last_three_mnths». Однако способ, которым вы хотите, чтобы ваш результат мог быть достигнут с помощью Map-Reduce.

Модифицированный Dataset я использовал,

db.user.insert({ 
    "_id" : 1, 
    "history" : { 
    "authors" : [ 
     { 
     "name" : "michou", 
     "count" : { 
      "all" : 400, 
      "2014" : 300, 
      "201408" : 200, 
      "2014w35" : 100 
     } 
     } 
    ] 
    } 
}); 
db.user.insert({ 
    "_id" : 2, 
    "history" : { 
    "authors" : [ 
     { 
     "name" : "petitBonhommeEnMousse", 
     "count" : { 
      "all" : 200, 
      "2014" : 100, 
      "201408" : 50, 
      "2014w35" : 25 
     } 
     }, 
     { 
     "name" : "lordVador", 
     "count" : { 
      "all" : 300, 
      "2014" : 200, 
      "201408" : 100, 
      "2014w35" : 50 
     } 
     } 
    ] 
    } 
}); 

Вот мой выстрел на это с помощью карты уменьшить (с тем же набором данных, как описано выше), надеюсь, что это помогает:

var map = function(){emit(this._id,{"author":this.history.authors});} 
var reduce = function(userid,authors_arr){ 
var reduced = {"user_views":[]}; 
for(var i in authors_arr) 
{ 
    var author_array = authors_arr[i]; 
    var authors = author_array.author; 
    for(var j in authors) 
    { 
     var author = authors[j]; 
     reduced.user_views.push({"author_name":author.name,"views":author.count.all}); 
    } 
} 
return reduced; 
} 

db.user.mapReduce(map,reduce,{ out: "output" }) 

[ 
    { 
    "_id": 1, 
    "value": { 
     "user_views": [ 
     { 
      "author_name": "michou", 
      "views": 400 
     } 
     ] 
    } 
    }, 
    { 
    "_id": 2, 
    "value": { 
     "user_views": [ 
     { 
      "author_name": "petitBonhommeEnMousse", 
      "views": 200 
     }, 
     { 
      "author_name": "lordVador", 
      "views": 300 
     } 
     ] 
    } 
    } 
] 

Примечание: Вам нужно изменить свои соглашения об именах ключей, например. '201408 'не является допустимым атрибутом java-скрипта. После того как вы изменили их, вы можете изменить функцию «уменьшить», чтобы получить сумму недельных просмотров.

+0

Привет, Вы, например, не работаете, ничего не возвращает. Но я думаю, что ты прав, я буду использовать карту-сокращение. Агрегационная фреймворк работает быстрее, но, похоже, невозможно добиться того, чего я хочу. –

+0

Да, это было бы не так, если бы вы скопировали и приклеились напрямую. Они содержали индикаторы («, ..») для указания количества добавленных недельных отсчетов. Удали его сейчас. Кроме того, я должен был внести некоторые изменения локально в ваш код, например, для вызова идентификаторов, удаления некоторых записей. Включили набор данных, который я использовал. И да, Map-reduce - это решение. – BatScream

+0

Ах, нет, это было не так, конечно, я меняю ... это просто я пропускаю имя коллекции ... Да, это работает. Но я не могу упорядочить их по наиболее используемым или ограниченным трем наиболее используемым. Я буду использовать уменьшение карты, чем. Благодарю. –

0

Возможно, вы можете попробовать «$ addToSet» для вашего второго attemp. Добавьте авторов и читайте числа в набор. Если автор уникален для каждого пользователя, «$ push» в порядке. http://docs.mongodb.org/manual/reference/operator/aggregation/push/

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

  • Нет связанных вопросов^_^