如何在 MongoDB 映射函数内对 BSON 对象进行字符串化?
我有包含字段 xyz
的文档
{ term: "puppies", page: { skip: 1, per_page: 20 } } // not useful as a composite key...
{ page: { skip: 1, per_page: 20 }, term: "puppies" } // different order, same contents
为了确定 xyz 中的“顶部”值,我想将它们全部映射到类似的东西,
emit('term="puppies",page={ skip: 1, per_page: 20 }', 1); // composite key
但我无法将嵌入的对象放入有意义的字符串中:
emit('term="puppies",page=[object bson_object]', 1); // not useful
对于使用函数代替 toString() 有什么建议吗?
# return the top <num> values of <field> based on a query <selector>
#
# example: top(10, :xyz, {}, {})
def top(num, field, selector, opts = {})
m = ::BSON::Code.new <<-EOS
function() {
var keys = [];
for (var key in this.#{field}) {
keys.push(key);
}
keys.sort ();
var sortedKeyValuePairs = [];
for (i in keys) {
var key = keys[i];
var value = this.#{field}[key];
if (value.constructor.name == 'String') {
var stringifiedValue = value;
} else if (value.constructor.name == 'bson_object') {
// this just says "[object bson_object]" which is not useful
var stringifiedValue = value.toString();
} else {
var stringifiedValue = value.toString();
}
sortedKeyValuePairs.push([key, stringifiedValue].join('='));
}
// hopefully we'll end up with something like
// emit("term=puppies,page={skip:1, per_page:20}")
// instead of
// emit("term=puppies,page=[object bson_object]")
emit(sortedKeyValuePairs.join(','), 1);
}
EOS
r = ::BSON::Code.new <<-EOS
function(k, vals) {
var sum=0;
for (var i in vals) sum += vals[i];
return sum;
}
EOS
docs = []
collection.map_reduce(m, r, opts.merge(:query => selector)).find({}, :limit => num, :sort => [['value', ::Mongo::DESCENDING]]).each do |doc|
docs.push doc
end
docs
end
I have documents with field xyz
containing
{ term: "puppies", page: { skip: 1, per_page: 20 } } // not useful as a composite key...
{ page: { skip: 1, per_page: 20 }, term: "puppies" } // different order, same contents
For the sake of determining the "top" values in xyz, I want to map them all to something like
emit('term="puppies",page={ skip: 1, per_page: 20 }', 1); // composite key
but I can't get the embedded objects into a meaningful strings:
emit('term="puppies",page=[object bson_object]', 1); // not useful
Any suggestions for a function to use instead of toString()
?
# return the top <num> values of <field> based on a query <selector>
#
# example: top(10, :xyz, {}, {})
def top(num, field, selector, opts = {})
m = ::BSON::Code.new <<-EOS
function() {
var keys = [];
for (var key in this.#{field}) {
keys.push(key);
}
keys.sort ();
var sortedKeyValuePairs = [];
for (i in keys) {
var key = keys[i];
var value = this.#{field}[key];
if (value.constructor.name == 'String') {
var stringifiedValue = value;
} else if (value.constructor.name == 'bson_object') {
// this just says "[object bson_object]" which is not useful
var stringifiedValue = value.toString();
} else {
var stringifiedValue = value.toString();
}
sortedKeyValuePairs.push([key, stringifiedValue].join('='));
}
// hopefully we'll end up with something like
// emit("term=puppies,page={skip:1, per_page:20}")
// instead of
// emit("term=puppies,page=[object bson_object]")
emit(sortedKeyValuePairs.join(','), 1);
}
EOS
r = ::BSON::Code.new <<-EOS
function(k, vals) {
var sum=0;
for (var i in vals) sum += vals[i];
return sum;
}
EOS
docs = []
collection.map_reduce(m, r, opts.merge(:query => selector)).find({}, :limit => num, :sort => [['value', ::Mongo::DESCENDING]]).each do |doc|
docs.push doc
end
docs
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
鉴于 MongoDB 使用 SpiderMonkey 作为其内部 JS 引擎,你不能吗使用
JSON.stringify
(将即使/当 MongoDB 切换到 V8 时也能工作)或 SpiderMonkey 的非标准toSource
方法?(抱歉,无法尝试 ATM 来确认其是否有效)
Given that MongoDB uses SpiderMonkey as its internal JS engine, can't you use
JSON.stringify
(will work even if/when MongoDB switches to V8) or SpiderMonkey's non-standardtoSource
method?(sorry, can't try it ATM to confirm it'd work)
toSource 方法 可以完成这项工作,但它还添加了括号。
对于干净的文档使用:
toSource method will do the work, but it adds also brackets.
for a clean document use: