2015-07-14 7 views
1

У нас есть поле (ы) в MongoDB, который имеет число в виде строки, значение, такие как «$ 123,00,89.00» или «1234 $» и т.д.Сумма подстрок в MongoDB

Можно настроить $ суммы аккумуляторов в mongodb, так что определенная обработка может быть выполнена при каждом значении поля при выполнении суммы. Такие, как обработка подстроки или reg-ex и т. Д.

ответ

1

Метод .mapReduce() - это то, что вам нужно здесь. Вы не можете «отличать» значения в aggregation framework от одного «типа» к другому (за исключением «до строки» или от Date до числового).

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

db.collection.mapReduce(
    function() { 
     emit(null, this.amount.replace(/\$|,|\./g,"")/100); 
    }, 
    function(key,values) { 
     return Array.sum(values); 
    }, 
    { "out": { "inline": 1 } } 
) 

Или с .group() который также использует JavaScript ОБРАБОТКИ, но это немного больше restrcitive в его требованиях:

db.collection.group({ 
    "key": null, 
    "reduce": function(curr,result) { 
     result.total += curr.amount.replace(/\$|,|\./g,"") /100; 
    }, 
    "initial": { "total": 0 } 
}); 

так JavaScript обработка единственный вариант, поскольку эти виды деятельности не поддерживаются в рамках aggregatation

номер может быть строкой:.

db.junk.aggregate([{ "$project": { "a": { "$substr": [ 1,0,1 ] } } }]) 
{ "_id" : ObjectId("55a458c567446a4351c804e5"), "a" : "1" } 

И Date может стать номер:

db.junk.aggregate([{ "$project": { "a": { "$subtract": [ new Date(), new Date(0) ] } } }]) 
{ "_id" : ObjectId("55a458c567446a4351c804e5"), "a" : NumberLong("1436835669446") } 

Но нет никаких других операторов «слепок» «строка» в «Числовой» или даже Anthing, чтобы сделать Regex заменить, как показано выше.

Если вы хотите использовать .aggregate(), то вам необходимо исправить свои данные в формат, который будет поддерживать его, таким образом, «Числовой»:

var bulk = db.collection.initializeOrderedBulkOp(), 
    count = 0; 

db.collection.find({ "amount": /\$|,\./g }).forEach(function(doc) { 
    doc.amount = doc.amount.replace(/\$|,|\./g,"") /100; 
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { "amount": doc.amount } 
    }); 
    count++; 

    // execute once in 1000 operations 
    if (count % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.collection.initializeOrderedBulkOp(); 
    } 
}); 

// clean up queued operations 
if (count % 1000 != 0) 
    bulk.execute(); 

Затем вы можете использовать .aggregate() на вашей «цифровой» данные:

db.collection.aggregate([ 
    { "$group": { "_id": null, "total": { "$sum": "$amount" } } } 
]) 
Смежные вопросы