【问题标题】:Why can a MongoDb cursor be indexed as if it was an array?为什么 MongoDb 游标可以像数组一样被索引?
【发布时间】:2014-08-10 10:28:01
【问题描述】:

我注意到,如果我使用 mongo 命令执行 JavaScript 脚本,该脚本可以将光标对象视为数组。

var conn = new Mongo('localhost:27017');
var db = conn.getDB('learn');
db.test.remove({});
db.test.insert({foo: 'bar'});
var cur = db.test.find();
print(cur[0].foo);   //prints: bar
print(cur[1]); // prints: undefined

这似乎超出了 JavaScript 语言的能力,因为没有办法“重载下标运算符”。那么这实际上是如何工作的呢?

【问题讨论】:

  • 每个文档都可以通过它的索引来访问...如果你访问的文档数量超出了,它会返回“undefined”
  • 它可能不会操纵运算符,但它可以操纵索引。由于它们只是属性的一个子集,它们可以是defined as getters and/or settersObject.defineProperty(cursor, '0', { get: ... });
  • @JonathanLonowski 但是如果没有“方法缺失”,则必须为每个索引定义一个运算符,这在这里似乎不切实际..
  • @user2864740 不,像 dt0xff 提到的那样访问本机代码可能不切实际。但是,我主要是指出可以在没有运算符重载的情况下定义一个类似数组的对象。
  • @JonathanLonowski,事实并非如此。看看游标类 github.com/mongodb/mongo/blob/master/src/mongo/shell/query.js ,这里我们没有类似于这个的逻辑,这是我首先检查的,但是 mongo 这样做会很愚蠢,是的。但在某些情况下,如果您试图模仿这种行为,它可能会很方便。

标签: javascript arrays mongodb


【解决方案1】:

如文档所述,it is special ability of driver。它自动cursor[0] 转换为cursor.toArray()[0]。您可以通过使用 print 函数覆盖 toArray()new Error().stack 来获取调用堆栈来证明这一点。这里是:

at DBQuery.a.toArray ((shell):1:32)
at DBQuery.arrayAccess (src/mongo/shell/query.js:290:17)
at (shell):1:2

如您所见,索引调用arrayAccess。如何? Here we have a dbQueryIndexAccess function,它调用arrayAccess

v8::Handle<v8::Value> arrayAccess = info.This()->GetPrototype()->ToObject()->Get(
                v8::String::New("arrayAccess"));
...
v8::Handle<v8::Function> f = arrayAccess.As<v8::Function>();
...
return f->Call(info.This(), 1, argv);

还有here we have a code,它将索引属性处理程序设置为此函数。哇,v8 API 让我们能够添加这个处理程序!

DBQueryFT()->InstanceTemplate()->SetIndexedPropertyHandler(dbQueryIndexAccess);

...并将其注入到JS中原始定义的JS游标类中。

injectV8Function("DBQuery", DBQueryFT(), _global);

Tl;dr:在 mongo shell 的 C++ 源代码中被黑了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 1970-01-01
    • 2023-01-08
    相关资源
    最近更新 更多