如何在 MongoDB 映射函数内对 BSON 对象进行字符串化?

发布于 2024-11-02 16:10:18 字数 2047 浏览 5 评论 0原文

我有包含字段 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酒与心事 2024-11-09 16:10:18

鉴于 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-standard toSource method?

(sorry, can't try it ATM to confirm it'd work)

人间不值得 2024-11-09 16:10:18

toSource 方法 可以完成这项工作,但它还添加了括号。
对于干净的文档使用:

value.toSource().substring(1, value.toSource().length - 1)

toSource method will do the work, but it adds also brackets.
for a clean document use:

value.toSource().substring(1, value.toSource().length - 1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文