MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

сборната заявка на mongodb не връща правилната сума при използване на $sum

Текущата ви схема има marks поле тип данни като низ и имате нужда от целочислен тип данни за вашата рамка за агрегиране, за да изчислите сумата. От друга страна, можете да използвате MapReduce за изчисляване на сумата, тъй като позволява използването на собствени JavaScript методи като parseInt() върху свойствата на вашия обект в неговите функции за карта. Така че като цяло имате два избора.

Опция 1:Актуализиране на схема (промяна на типа данни)

Първото би било да промените схемата или да добавите друго поле във вашия документ, което има действителната числена стойност, а не представянето на низ. Ако размерът на вашия документ за колекция е сравнително малък, можете да използвате комбинация от курсора на mongodb find() , forEach() и update() методи за промяна на вашата схема за маркировки:

db.student.find({ "marks": { "$type": 2 } }).snapshot().forEach(function(doc) {
    db.student.update(
        { "_id": doc._id, "marks": { "$type": 2 } }, 
        { "$set": { "marks": parseInt(doc.marks) } }
    );
});

За сравнително големи размери на колекция, вашата db производителност ще бъде бавна и се препоръчва да използвате групови актуализации на mongo за това:

Версии на MongoDB>=2.6 и <3.2:

var bulk = db.student.initializeUnorderedBulkOp(),
    counter = 0;

db.student.find({"marks": {"$exists": true, "$type": 2 }}).forEach(function (doc) {    
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "marks": parseInt(doc.marks) } 
    });

    counter++;
    if (counter % 1000 === 0) {
        // Execute per 1000 operations 
        bulk.execute(); 

        // re-initialize every 1000 update statements
        bulk = db.student.initializeUnorderedBulkOp();
    }
})

// Clean up remaining operations in queue
if (counter % 1000 !== 0) bulk.execute(); 

MongoDB версия 3.2 и по-нова:

var ops = [],
    cursor = db.student.find({"marks": {"$exists": true, "$type": 2 }});

cursor.forEach(function (doc) {     
    ops.push({ 
        "updateOne": { 
            "filter": { "_id": doc._id } ,              
            "update": { "$set": { "marks": parseInt(doc.marks) } } 
        }         
    });

    if (ops.length === 1000) {
        db.student.bulkWrite(ops);
        ops = [];
    }     
});

if (ops.length > 0) db.student.bulkWrite(ops);

Вариант 2:Стартирайте MapReduce

Вторият подход би бил да пренапишете вашата заявка с MapReduce където можете да използвате функцията на JavaScript parseInt() .

Във вашия MapReduce операция, дефинирайте функцията за карта, която обработва всеки входен документ. Тази функция картографира преобразуваните marks низова стойност към subject за всеки документ и излъчва subject и конвертирани marks двойка. Тук е основната функция на JavaScript parseInt() може да се прилага. Забележка:във функцията, this се отнася до документа, който операцията за намаляване на картата обработва:

var mapper = function () {
    var x = parseInt(this.marks);
    emit(this.subject, x);
};

След това дефинирайте съответната функция за намаляване с два аргумента keySubject и valuesMarks . valuesMarks е масив, чиито елементи са целите числа marks стойности, излъчвани от функцията map и групирани по keySubject .Функцията намалява valuesMarks масив към сумата от неговите елементи.

var reducer = function(keySubject, valuesMarks) {
    return Array.sum(valuesMarks);
};

db.student.mapReduce(
    mapper,
    reducer,
    {
        out : "example_results",
        query: { subject : "maths" }       
    }
 );

С вашата колекция горното ще постави вашия резултат от агрегирането на MapReduce в нова колекция db.example_results . Така, db.example_results.find() ще изведе:

/* 0 */
{
    "_id" : "maths",
    "value" : 163
}


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Върнете BsonDocument в ApiController

  2. Преименувайте ObjectId _id на id при десериализация на Jackson с Jongo и MongoDB

  3. Включва резервно криптиране за MySQL, MongoDB и PostgreSQL - ClusterControl 1.5.1

  4. MongoDb:Предимство от използването на ObjectID спрямо низ, съдържащ идентификатор?

  5. Как да получите данни Mongo данни с помощта на агрегат MongoDB