gpt4 book ai didi

node.js - 根据条件从现有字段计算分数

转载 作者:可可西里 更新时间:2023-11-01 09:39:58 25 4
gpt4 key购买 nike

我正在使用 MongoDB 2.6.9 和 NodeJs 0.10.37,我有一个集合 vols,意思是航类。

> db.vols.findOne()
{
"_id" : ObjectId("5717a5d4578f3f2556f300f2"),
"Orig" : "AGP",
"Dest" : "OTP",
"Flight" : 126,
"Routing" : "AGP-OTP",
"Stops" : 0,
"Seats" : 169,
"Ops_Week" : 3,
"Eff_Date" : "2016-04-14",
"Mkt_Al" : "0B",
"Dep_Time" : 1110,
"Thru_Point" : "",
"Arr_Time" : 1600,
"Block_Mins" : 230

}

每份文件都是指航空公司完成的一次航类,并提供详细信息,例如,前一份文件是指直接完成的航类(Stops : 0)。但是下一个,飞机停了。

db.vols.findOne({Stops:1})
{
"_id" : ObjectId("5717a5d4578f3f2556f301c5"),
"Orig" : "CEK",
"Dest" : "IKT",
"Flight" : 7756,
"Routing" : "KZN-CEK-OVB-IKT",
"Stops" : 1,
"Seats" : 70,
"Ops_Week" : 2,
"Eff_Date" : "2016-04-11",
"Mkt_Al" : "2G",
"Dep_Time" : 1655,
"Thru_Point" : "OVB",
"Arr_Time" : 140,
"Block_Mins" : 345
}

重要:

每个 Airline 在每条路线( Origin - Destination )中都有一个 score

如何计算分数?

enter image description here

因此,我需要进行这些计算并将新字段“QSI”插入到我的集合 vols 中。

重要:

c4 中的平均运行时间意味着:

例如,我们有一个带停靠站的航类,比方说:从AC的航类由B,例如,整个航类60分钟,但是从AB是20分钟,从BC是20分钟,这个平均值应该在 40 分钟后返回。

我试过这个解决方案,但对于 c4 来说,事情看起来不太管用:

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

mongoose.connect('mongodb://localhost/ramtest');

var volsSchema = new Schema({}, { strict : false, collection : 'vols' });
var MyModel = mongoose.model("MyModel", volsSchema);

mongoose.set('debug', true);

mongoose.connection.on("open", function(err) {
if (err) throw err;

var bulkUpdateOps = MyModel.collection.initializeUnorderedBulkOp(),
counter = 0;

MyModel.find({}).lean().exec(function(err, docs) {
if (err) throw err;

docs.forEach(function(doc) {
// computations
var c1, c2, c3, c4, qsi, first_leg, second_leg, total_flight;

c1 = 0.3728 + (0.00454 * doc.Seats);
c2 = (doc.Stops == 1) ? 0.03 : 1;
c3 = doc.Ops_Week;

if (doc.Stops == 1) {
var Mkt_Air = doc.Mkt_Al,
Origin = doc.Orig,
Destination = doc.Dest,
Thru_Point = doc.Thru_Point,
Effective_Date = doc.Eff_Date,
Block_Mins = doc.Block_Mins;

MyModel.find({ Mkt_Al : Mkt_Air }, { Orig : Origin }, { Dest : Thru_Point }, { Eff_Date : Effective_Date }).lean().exec(function(err, docs) {
docs.forEach(function(doc) {
var first_leg = doc.Block_Mins;
MyModel.find({ Mkt_Al : Mkt_Air }, { Orig : Thru_Point }, { Dest : Destination }, { Eff_Date : Effective_Date }).lean().exec(function(err, docs) {
docs.forEach(function(doc) {
var second_leg = doc.Block_Mins, total_flight = second_leg + first_leg;
c4 = Math.pow((Block_Mins / total_flight), -0.675);
qsi = c1 * c2 * c3 * c4;
}); // the end of docs.forEach(function (doc){
}); // the end of MyModel.find..
}); // the end of docs.forEach(function (doc){
}); // the end of MyModel.find..
} // end if
else {
c4 = 1;
}

qsi = c1 * c2 * c3 * c4;

counter++;

bulkUpdateOps.find({ "_id" : doc._id }).updateOne({
"$set" : { "Qsi" : qsi }
});

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

});

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

var app = express();
app.listen(3000, function() {
console.log('Ready to calculate and insert the QSI');
});
});

问题:

我认为问题出在 MyModel.find 上,如果我在这条指令中丢失了数据...,我的 scoreStops = 0,但如果 Stops = 1,我的分数取值为 Nan,并且在像 callback(null, docs) 请问谁能帮忙??

我怎样才能实现上述目标?

最佳答案

您的实现存在多个问题。首先,您使用的是 find() 方法不正确,因为您为查询指定了太多参数:

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

应该是

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

同样,您不应该使用 find() 方法,因为您只需要一个与查询匹配的文档即可用于您的计算。从您之前关闭的问题中提取复杂的算法:

Now I want to calculate a score c4 and insert it into my collection :

To do that I should calculate a value c4 just like this :

1) First I verify for each document if ( Field2 == 1 ) if it's true I continue else it's simple c4 takes value 1.

2) Then I should make a loop "for" and see which document verify these conditions : doc.Field1 == this.Field1 && doc.Field6 == this.Field6 &&
doc.Field7 == this.Field8

3) Then I take doc.Field4 wich will be added to another document's Field4

4) I continue and I make another loop and look for another document wich verify these conditions :

it should have the same Field1 just like the previous document and its Field6 equal to the previous document Field7 and its Field8 the same as Field8 in the first document

5) Then I take doc.Field4 and add it to the previous doc.Field4

使用 MyModel.findOne() 应该足以完成上面的任务 3、4 和 5。但是,由于调用的异步性质,您需要嵌套查询,但幸运的是嵌套调用的深度不超过 3,否则您会发现自己有一张通往回调 hell 的单程票。为了避免这些常见的陷阱,最好使用 Promises (因为默认情况下 native Mongoose 查询可以返回 Promise )或使用 node-async 包,其中包含许多用于处理此类情况的函数。

如果使用 async 库,它允许您高效地运行多个相互依赖的异步任务(如 MyModel.findOne() 调用),当它们全部完成时执行其他操作。在上面,您可以使用 async.series() 方法。


以下示例演示了上述概念,您可以在其中根据测试数据库中的以下示例文档计算 Qsi

填充测试数据库的 vol 集合:

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 应用:

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);
});
}
});
});

示例输出:

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
}

关于node.js - 根据条件从现有字段计算分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37791777/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com