sql >> Databasteknik >  >> NoSQL >> MongoDB

Beräkna en poäng från ett befintligt fält med villkor

Det finns flera problem med din implementering. För det första använder du find() metod felaktigt eftersom du anger för många argument för frågan:

MyModel.find(
    { Mkt_Al : Mkt_Air }, 
    { Orig : Origin }, 
    { Dest : Thru_Point }, 
    { Eff_Date : Effective_Date }
).lean().exec(function(err, docs) { .. }

borde vara

MyModel.find({ 
    Mkt_Al: Mkt_Air, 
    Orig: Origin, 
    Dest: Thru_Point, 
    Eff_Date: Effective_Date 
}).lean().exec(function(err, docs) { ... }

Återigen, du bör inte använda find() metod i det här fallet eftersom du bara behöver ett enda dokument som matchar frågan att använda i dina beräkningar. Med den komplexa algoritmen från din tidigare stängda fråga:

Använda MyModel.findOne() bör räcka för uppgifterna 3, 4 och 5 ovan. Men på grund av samtalens asynkrona natur skulle du behöva kapsla frågorna men lyckligtvis är djupet på de kapslade samtalen inte större än 3, annars kommer du att få en enkelbiljett till Callback Hell. För att undvika dessa vanliga fallgropar är det bättre att använda Löfter (eftersom de inbyggda mongoose-frågorna som standard kan returnera ett Löfte ) eller använd node-async paket som innehåller ett antal funktioner för att hantera situationer som denna.

Om du använder async biblioteket, låter det dig effektivt köra flera asynkrona uppgifter (som MyModel.findOne() samtal) som är beroende av varandra och när de alla är klara gör något annat. I ovanstående kan du använda async.series() metod.

Följande exempel visar konceptet ovan där du kan beräkna Qsi från följande exempeldokument i testdb.

Följ test db:s volymsamling:

db.vols.insert([
    {    
        "Mkt_Al" : "2G",
        "Stops" : 0,
        "Seats" : 169,
        "Block_Mins" : 230,                
        "Ops_Week" : 3,        
        "Orig" : "AGP",
        "Dest" : "OTP",
        "Thru_Point" : "",
    },
    {    
        "Mkt_Al" : "2G",
        "Stops" : 1,
        "Seats" : 260,              
        "Block_Mins" : 260,
        "Ops_Week" : 2,  
        "Orig" : "CEK",
        "Dest" : "IKT",
        "Thru_Point" : "OVB",
    },
    {    
        "Mkt_Al" : "2G",
        "Stops" : 0,
        "Seats" : 140,
        "Block_Mins" : 60,
        "Ops_Week" : 2,        
        "Orig" : "BEK",
        "Dest" : "OTP",
        "Thru_Point" : "",
    },
    {    
        "Mkt_Al" : "2G",
        "Stops" : 0,
        "Seats" : 160,
        "Block_Mins" : 90,
        "Ops_Week" : 3,        
        "Orig" : "CEK",
        "Dest" : "OVB",
        "Thru_Point" : "",
    },
    {    
        "Mkt_Al" : "2G",        
        "Stops" : 0,
        "Seats" : 60,
        "Block_Mins" : 50,
        "Ops_Week" : 3,        
        "Orig" : "OVB",
        "Dest" : "IKT",
        "Thru_Point" : "",
    }
])

Node.js-appen:

var mongoose = require('mongoose'),
    express = require('express'),
    async = require('async'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');
var volSchema = new Schema({},{ strict: false, collection: 'vols' }),    
    Vol = mongoose.model("Vol", volSchema);

mongoose.set('debug', false);

mongoose.connection.on("open", function (err) {
    if (err) throw err;  
    var bulkUpdateOps = Vol.collection.initializeUnorderedBulkOp(), 
        counter = 0;

    Vol.find({}).lean().exec(function (err, docs) {
        if (err) throw err; 
        var locals = {};

        docs.forEach(function(doc) {            
            locals.c1 = 0.3728 + (0.00454 * doc.Seats);         
            locals.c3 = doc.Ops_Week;

            if (doc.Stops == 1) {               
                async.series([
                    // Load doc with first leg first
                    function(callback) {
                        Vol.findOne({ 
                            Mkt_Al: doc.Mkt_Al,
                            Orig: doc.Orig,
                            Dest: doc.Dest                          
                        }).lean().exec(function (err, flight) {
                            if (err) return callback(err);
                            locals.first_leg = flight.Block_Mins;
                            callback();
                        });
                    },
                    // Load second leg doc 
                    // (won't be called before task 1's "task callback" 
                    // has been called)
                    function(callback) {                    
                        Vol.findOne({ 
                            Mkt_Al: doc.Mkt_Al,
                            Orig: doc.Thru_Point,
                            Dest: doc.Dest                          
                        }).lean().exec(function (err, flight) {
                            if (err) return callback(err);
                            locals.second_leg = flight.Block_Mins;
                            callback();
                        });
                    }
                ], function(err) { // This function gets called after the
                    // two tasks have called their "task callbacks"
                    if (err) throw err;
                    // Here locals will be populated with `first_leg` 
                    // and `second_leg`
                    // Just like in the previous example
                    var total_flight = locals.second_leg + locals.first_leg;                    
                    locals.c2 = 0.03;
                    locals.c4 = Math.pow((doc.Block_Mins / total_flight), -0.675);                    

                }); 
            } else {
                locals.c2 = 1;
                locals.c4 = 1;
            }

            counter++;
            console.log(locals);
            bulkUpdateOps.find({ "_id" : doc._id }).updateOne({ 
                "$set": { 
                    "Qsi": (locals.c1 * locals.c2 * locals.c3 * locals.c4) 
                } 
            });

            if (counter % 500 == 0) {
               bulkUpdateOps.execute(function(err, result) {          
                    if (err) throw err; 
                    bulkUpdateOps = Vol.collection.initializeUnorderedBulkOp();                        
                });
            } 
        });

        if (counter % 500 != 0) {
            bulkUpdateOps.execute(function(err, result) {
                if (err) throw err; 
                console.log(result.nModified);                
            });
        }   
    });
});

Exempel på utdata:

db.vols.find()

/* 1 */
{
    "_id" : ObjectId("5767e7549ebce6d574702221"),
    "Mkt_Al" : "2G",
    "Stops" : 0,
    "Seats" : 169,
    "Block_Mins" : 230,
    "Ops_Week" : 3,
    "Orig" : "AGP",
    "Dest" : "OTP",
    "Thru_Point" : "",
    "Qsi" : 3.42018
}

/* 2 */
{
    "_id" : ObjectId("5767e7549ebce6d574702222"),
    "Mkt_Al" : "2G",
    "Stops" : 1,
    "Seats" : 260,
    "Block_Mins" : 260,
    "Ops_Week" : 2,
    "Orig" : "CEK",
    "Dest" : "IKT",
    "Thru_Point" : "OVB",
    "Qsi" : 3.1064
}

/* 3 */
{
    "_id" : ObjectId("5767e7549ebce6d574702223"),
    "Mkt_Al" : "2G",
    "Stops" : 0,
    "Seats" : 140,
    "Block_Mins" : 60,
    "Ops_Week" : 2,
    "Orig" : "BEK",
    "Dest" : "OTP",
    "Thru_Point" : "",
    "Qsi" : 2.0168
}

/* 4 */
{
    "_id" : ObjectId("5767e7549ebce6d574702224"),
    "Mkt_Al" : "2G",
    "Stops" : 0,
    "Seats" : 160,
    "Block_Mins" : 90,
    "Ops_Week" : 3,
    "Orig" : "CEK",
    "Dest" : "OVB",
    "Thru_Point" : "",
    "Qsi" : 3.2976
}

/* 5 */
{
    "_id" : ObjectId("5767e7549ebce6d574702225"),
    "Mkt_Al" : "2G",
    "Stops" : 0,
    "Seats" : 60,
    "Block_Mins" : 50,
    "Ops_Week" : 3,
    "Orig" : "OVB",
    "Dest" : "IKT",
    "Thru_Point" : "",
    "Qsi" : 1.9356
}


  1. Hur bearbetar man infogningsförfrågningar i Spring Data innan man lägger till dem i MongoDB?

  2. Fel vid laddning av YAML-konfigurationsfiler i Rails

  3. mongoDB-uppdateringMånga med upsert true och $in i where condition

  4. Vad är MongoDB batch operation max storlek?