自定义函数计算列mongodb投影 [英] Custom functions calculated columns mongodb projection

查看:57
本文介绍了自定义函数计算列mongodb投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用投影来获取使用集合中列上的自定义函数计算出的列,但我找不到解决方法.我能做的是这样:

I am trying to use projection to get a column calculated using a custom function on columns in collection but I couldn't't figure a way how to do it. What I could do is this:

db.collection.aggregate([$project:{column1:1, calculatedCol: {$literal:[ jaro_Winkler("how to access column name")]}] )

该代码可能存在语法错误,因为我现在没有代码.

The code might have syntax error because I don't have the code with me right now.

推荐答案

您似乎认为可以在聚合管道中调用JavaScript函数,但是您不能这样做.您会误以为函数的结果实际上是变量的插值",无法在管道中执行.

You seem to think it is possible to call a JavaScript function in the aggregation pipeline, but you cannot do this. You are mistaking what is actually "interpolation" of a variable from a function result for execution within the pipeline.

例如,如果我这样做:

var getNumbers = function() { return [ 1,2,3 ] };

然后我称之为:

db.collection.aggregate([
    { "$project": {
        "mynums": getNumbers()
    }}  
])

然后,在JavaScript外壳中实际发生的情况是将值插入"和之前"将指令发送到服务器,如下所示:

Then what actually happens in the JavaScript shell the values are being "interpolated" and "before" the instruction is sent to the server, like this:

db.collection.aggregate([
    { "$project": {
        "mynums": [1,2,3]
    }}  
])

要进一步证明这一点,请将功能仅"存储在服务器上:

To further demonstrate that, store a function "only" on the server:

db.system.js.save({ "_id": "hello", "value": function() { return "hello" } })

然后尝试运行聚合语句:

Then try to run the aggregation statement:

db.collection.aggregate([
    { "$project": {
        "greeting": hello()
    }}  
])

这将导致异常:

E查询[main] ReferenceError:在(shell):1:69处未定义hello

E QUERY [main] ReferenceError: hello is not defined at (shell):1:69

这是因为执行是在客户端"而不是服务器"上执行的,并且该功能在客户端上不存在.

Which is because the execution is happening on the "client" and not the "server" and the function does not exist on the client.

聚合框架无法运行JavaScript,因为它没有规定.所有操作均以本机代码执行,而不会调用JavaScript引擎.因此,您改为在此处使用运算符:

The aggregation framework cannot run JavaScript, as it has no provision to do so. All operations are performed in native code, with no JavaScript engine being invoked. Therefore you use the operators there instead:

db.collection.aggregate([
    { "$project": {
        "total": { "$add": [ 1, 2 ] },
        "field_total": { "$subtract": [ "$gross", "$tax" ] }
    }}  
])   

如果您不能使用运算符来获得结果,那么运行JavaScript代码的唯一方法是运行 mapReduce 代替,它当然使用JavaScript引擎与集合中的数据进行交互.而且,如果需要,您还可以在逻辑中引用服务器端函数:

If you cannot use the operators to acheive the results then the only way you can run JavaScript code is to run mapReduce instead, which of course uses a JavaScript engine to interface with the data from the collection. And from there you can also referce a server side function inside your logic if you need to:

{ "key": 1, "value": 1 },
{ "key": 1, "value": 2 },
{ "key": 1, "value": 3 }

db.system.js.save({ "_id": "square", "value": function(num) { return num * num } })

db.collection.mapReduce(
    function() {
        emit(this.key,square(this.value))
    },
    function(key,values) {
        return Array.sum(values);
    },
    { "out": { "inline": 1 } }
)

返回:

{
    "_id": 1,
    "value": 14
}

因此,这与如何传递字段值"无关,而实际上与聚合框架不以任何方式支持JavaScript以及您认为发生的情况实际上并非如此有关.

So this is not about "how to pass in a field value" but really about the fact that the aggregation framework does not support JavaScript in any way, and that what you thought was happening is not actually the case.

这篇关于自定义函数计算列mongodb投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆