在聚合管道、MapReduce 或 runCommand 中使用存储的 JavaScript 函数
Using stored JavaScript functions in the Aggregation pipeline, MapReduce or runCommand
有没有办法在管道或 mapreduce 中使用另存为 db.system.js.save(...)
的用户定义函数?
您保存到 system.js
的任何函数都可供 "JavaScript" 处理语句使用,例如 $where
operator and mapReduce
并且可以被分配的 _id
值引用.
db.system.js.save({
"_id": "squareThis",
"value": function(a) { return a*a }
})
并且一些数据插入到 "sample" 集合中:
{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
然后:
db.sample.mapReduce(
function() {
emit(null, squareThis(this.a));
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
);
给出:
"results" : [
{
"_id" : null,
"value" : 14
}
],
或 $where
:
db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
但在 "neither" 情况下,您可以使用全局变量,例如数据库 db
引用或其他函数。 $where
和 mapReduce
文档都包含您可以在此处执行的操作的限制信息。所以如果你认为你会做类似 "look up data in another collection" 的事情,那么你可以忘记它,因为它是 "Not Allowed".
每个 MongoDB命令操作实际上是调用"runCommand"操作"under the hood"反正。但是除非该命令实际执行的操作是 "calling a JavaScript processing engine" 否则用法就变得无关紧要了。无论如何只有少数命令可以执行此操作,如 mapReduce
、group
或 eval
,当然还有 $where
.
的查找操作
聚合框架不以任何方式使用JavaScript。您可能会误会,就像其他人所做的这样的声明一样,它并没有按照您的想法行事:
db.sample.aggregate([
{ "$match": {
"a": { "$in": db.sample.distinct("a") }
}}
])
所以那是 "not running inside" 聚合管道,而是那个 .distinct()
调用的 "result" 是 "evaluated" 之前管道被发送到服务器。就像外部变量一样完成:
var items = [1,2,3];
db.sample.aggregate([
{ "$match": {
"a": { "$in": items }
}}
])
两者基本上以相同的方式发送到服务器:
db.sample.aggregate([
{ "$match": {
"a": { "$in": [1,2,3] }
}}
])
所以它是 "not possible" 到 "call" 聚合管道中的任何 JavaScript 函数,也没有任何意义是 "passing in" 通常来自保存在system.js
。 "code" 需要是 "loaded to the client" 并且只有 JavaScript 引擎才能真正用它做任何事情。
使用聚合框架,所有可用的 "operators" 实际上都是本机编码函数,而不是为 mapReduce
提供的 "free form" JavaScript 解释。所以不用写 "JavaScript",而是使用运算符本身:
db.sample.aggregate([
{ "$group": {
"_id": null,
"sqared": { "$sum": {
"$multiply": [ "$a", "$a" ]
}}
}}
])
{ "_id" : null, "sqared" : 14 }
因此,您可以使用 system.js 中保存的函数执行的操作存在限制,并且您想要执行的操作很可能是:
- 不允许,例如从另一个集合访问数据
- 不是真的需要,因为逻辑通常是自包含的
- 或者可能更好地以客户端逻辑或其他不同形式实现
我真正能想到的唯一实际用途是,您有许多 "mapReduce" 操作无法通过任何其他方式完成,并且您有各种 "shared" 功能,您更愿意只存储在服务器上而不是在每个 mapReduce 函数调用中维护。
但话又说回来,mapReduce 优于聚合框架的 90% 原因通常是 "document structure" 集合选择不当,JavaScript 功能是 "required"遍历文档进行搜索分析。
因此您可以在允许的限制下使用它,但在大多数情况下您可能根本不应该使用它,而是解决其他让您认为您首先需要此功能的问题。
有没有办法在管道或 mapreduce 中使用另存为 db.system.js.save(...)
的用户定义函数?
您保存到 system.js
的任何函数都可供 "JavaScript" 处理语句使用,例如 $where
operator and mapReduce
并且可以被分配的 _id
值引用.
db.system.js.save({
"_id": "squareThis",
"value": function(a) { return a*a }
})
并且一些数据插入到 "sample" 集合中:
{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
然后:
db.sample.mapReduce(
function() {
emit(null, squareThis(this.a));
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
);
给出:
"results" : [
{
"_id" : null,
"value" : 14
}
],
或 $where
:
db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
但在 "neither" 情况下,您可以使用全局变量,例如数据库 db
引用或其他函数。 $where
和 mapReduce
文档都包含您可以在此处执行的操作的限制信息。所以如果你认为你会做类似 "look up data in another collection" 的事情,那么你可以忘记它,因为它是 "Not Allowed".
每个 MongoDB命令操作实际上是调用"runCommand"操作"under the hood"反正。但是除非该命令实际执行的操作是 "calling a JavaScript processing engine" 否则用法就变得无关紧要了。无论如何只有少数命令可以执行此操作,如 mapReduce
、group
或 eval
,当然还有 $where
.
聚合框架不以任何方式使用JavaScript。您可能会误会,就像其他人所做的这样的声明一样,它并没有按照您的想法行事:
db.sample.aggregate([
{ "$match": {
"a": { "$in": db.sample.distinct("a") }
}}
])
所以那是 "not running inside" 聚合管道,而是那个 .distinct()
调用的 "result" 是 "evaluated" 之前管道被发送到服务器。就像外部变量一样完成:
var items = [1,2,3];
db.sample.aggregate([
{ "$match": {
"a": { "$in": items }
}}
])
两者基本上以相同的方式发送到服务器:
db.sample.aggregate([
{ "$match": {
"a": { "$in": [1,2,3] }
}}
])
所以它是 "not possible" 到 "call" 聚合管道中的任何 JavaScript 函数,也没有任何意义是 "passing in" 通常来自保存在system.js
。 "code" 需要是 "loaded to the client" 并且只有 JavaScript 引擎才能真正用它做任何事情。
使用聚合框架,所有可用的 "operators" 实际上都是本机编码函数,而不是为 mapReduce
提供的 "free form" JavaScript 解释。所以不用写 "JavaScript",而是使用运算符本身:
db.sample.aggregate([
{ "$group": {
"_id": null,
"sqared": { "$sum": {
"$multiply": [ "$a", "$a" ]
}}
}}
])
{ "_id" : null, "sqared" : 14 }
因此,您可以使用 system.js 中保存的函数执行的操作存在限制,并且您想要执行的操作很可能是:
- 不允许,例如从另一个集合访问数据
- 不是真的需要,因为逻辑通常是自包含的
- 或者可能更好地以客户端逻辑或其他不同形式实现
我真正能想到的唯一实际用途是,您有许多 "mapReduce" 操作无法通过任何其他方式完成,并且您有各种 "shared" 功能,您更愿意只存储在服务器上而不是在每个 mapReduce 函数调用中维护。
但话又说回来,mapReduce 优于聚合框架的 90% 原因通常是 "document structure" 集合选择不当,JavaScript 功能是 "required"遍历文档进行搜索分析。
因此您可以在允许的限制下使用它,但在大多数情况下您可能根本不应该使用它,而是解决其他让您认为您首先需要此功能的问题。