2015-07-08 4 views
2

Возможно ли агрегировать данные, которые хранятся через DBRef?MongoDB Агрегация с DBRef

Монго 2,6

Допустим, у меня есть данные о сделке, как:

{ 
    _id : ObjectId(...), 
    user : DBRef("user", ObjectId(...)), 
    product : DBRef("product", ObjectId(...)), 
    source : DBRef("website", ObjectId(...)), 
    quantity : 3, 
    price : 40.95, 
    total_price : 122.85, 
    sold_at : ISODate("2015-07-08T09:09:40.262-0700") 
} 

Хитрость заключается в «источник» является полиморфным в природе - это может быть различные значения $ реф, такие как «веб-страницы», " call_center "и т. д., которые также имеют разные ObjectIds. Например, DBRef («веб-страница», ObjectId («1»)) и DBRef («веб-страница», ObjectId («2»)) будут двумя разными веб-страницами, в которых возникла транзакция.

Я хотел бы, чтобы в конечном счете агрегированный от источника в течение определенного периода времени (например, месяц):

db.coll.aggregate({ $match : { sold_at : { $gte : start, $lt : end } } }, 
        { $project : { source : 1, total_price : 1 } }, 
        { $group : { 
         _id : { "source.$ref" : "$source.$ref" }, 
         count : { $sum : $total_price } 
         } }); 

Хитрость есть вы получите ошибку путь пытается использовать переменную начиная с $ либо пытается группы или путем преобразования с помощью выражений через проект.

Любой способ сделать это? Фактически пытаясь перетащить эти данные через агрегацию в подмножество, чтобы работать там. Попытка избежать большой операции курсора над миллионами записей для преобразования данных, чтобы я мог ее заполнить.

ответ

0

Нельзя использовать значения DBRef с каркасом агрегации. Вместо этого вы должны использовать обработку JavasScript из mapReduce для того, чтобы получить доступ к свойству присвоения имен, которые они используют:

db.coll.mapReduce(
    function() { 
     emit(this.source.$ref, this["total_price"]) 
    }, 
    function(key,values) { 
     return Array.sum(values); 
    }, 
    { 
     "query": { "sold_at": { "$gte": start, "$lt": end } }, 
     "out": { "inline": 1 } 
    } 
) 

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

+0

спасибо, в значительной степени, что я думал. У меня есть способ обойти это путем «сглаживания» посредством агрегации навалом, что делает трюк лучше, чем один за другим, с помощью курсора. к сожалению, легче сказать, чем сделать, не используя DBRef в нашей хорошо установленной базе кода :-) – Jeff