2014-02-02 1 views
26

У меня есть список статей, и каждый из них имеет свойство массива в котором перечислены различные лица, упомянутые в них:MongoDB группа по массивов внутренних элементов-

_id: { 
$oid: "52b632a9e4f2ba13c82ccd23" 
}, 
providerName: "The Guardian", 
url: "http://feeds.theguardian.com/c/34708/f/663860/s/3516cebc/sc/38/l/0L0Stheguardian0N0Cmusic0C20A130Cdec0C220Cwaterboys0Efishermans0Eblues0Etour0Ehammersmith/story01.htm", 
subject: "The Waterboys – review", 
class_artist: [ 
"paul mccartney" 
] 

Я пытался (безуспешно) чтобы получить список всех отдельных художников (class_artist), в зависимости от количества статей, в которые они были помечены за последние 7 дней.

я получил, насколько:

var date = new Date(); 
date.setDate(date.getDate() - 7); 
db.articles.group({ 
       key: { class_artist: 1 }, 
       cond: { class_date: { $gt: date } }, 
       reduce: function (curr, result) { result.cnt++; }, 
       initial: { cnt : 0 } 
      }).sort({cnt: -1}); 

Но, к сожалению, она не будет считать их на основе индивидуальных значений массива, но композиции массива (то есть, списки художников).

Я пробовал использовать функцию $unwind, но не смог заставить ее работать.

ответ

76

Какие рамки вы используете? Это не оболочка MongoDB и выглядит как какая-то странная обертка вокруг MapReduce. В этом случае $unwind будет недоступен, и вам понадобится его для пользователя в aggregation framework. Вот то, что вы хотите в Монго оболочки:

db.articles.aggregate([ 
    {$match: { class_date: { $gte: date } } }, 
    {$project: { _id: 0, class_artist: 1 } }, 
    {$unwind: "$class_artist" }, 
    {$group: { _id: "$class_artist", tags: { $sum: 1 } }}, 
    {$project: { _id: 0,class_artist: "$_id", tags: 1 } }, 
    {$sort: { tags: -1 } } 
]) 

Так эффективно:

  1. Filter по дате, потому что вы уже установили вар за последние 7 дней
  2. Project только поля (s) мы нужно {Нам нужен только один! }
  3. Unwind массив таким образом, мы теперь имеем запись для каждого элемента массива в каждом документе
  4. Group на артиста из расширенных документов
  5. проекта в формат документа вы можете использовать в качестве группы возился с _ID
  6. Sort результатов в обратном порядке, чтобы увидеть вершину меченых первого

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

Встряхните и запекайте в свою собственную имплантацию или каркас ODM по мере необходимости.

+0

Спасибо за быстрый ответ! Работает как шарм. –

+2

FYI, формат «weird wrapper» - это команда '' group() '(http://docs.mongodb.org/manual/reference/command/group/), которая реализована в JavaScript и предшествует структуре агрегации. См. Также: [Сравнение агрегации MongoDB: group(), $ group и MapReduce] (http://stackoverflow.com/questions/12337319). – Stennie

+0

По какой-то причине совокупный метод всегда казался запутанным, но ответ действительно дал мне этот момент «лампочка» ... отличная работа =) – afreeland