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, но не смог заставить ее работать.


person Gil Adirim    schedule 02.02.2014    source источник


Ответы (1)


Какой фреймворк вы используете? Это не оболочка MongoDB и выглядит как какая-то странная оболочка вокруг MapReduce. В этом случае $ unwind будет недоступен, и он понадобится пользователю в структура агрегирования. Вот что вам нужно в оболочке mongo:

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. Фильтр по дате, поскольку вы уже установили переменную для последних 7 дней.
  2. Project только нужные нам поля {Нам нужно только одно! }
  3. Размотайте массив, чтобы теперь у нас была запись для каждого элемента массива в каждом документе.
  4. Группа по исполнителю из развернутых документов.
  5. Проект в формате документа, который вы можете использовать в качестве группы с _id
  6. Сортируйте результаты в обратном порядке, чтобы сначала увидеть верхние теги

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

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

person Neil Lunn    schedule 02.02.2014
comment
К вашему сведению, странный формат оболочки - это group() команда, реализованная в JavaScript. и предшествует Aggregation Framework. См. Также: Сравнение агрегации MongoDB: group (), $ group и MapReduce. - person Stennie; 02.02.2014