사용중인 MongoDB의 릴리스는 언급하지 않았지만 해결책은 여기에 제시된 것과 유사합니다. Ubuntu 13.04와 함께 제공되는 2.2.4를 설명합니다.
실제로이 문제는 커서에 옵션을 삽입하는 문제입니다. 그건 어디 addOption
삶 :
> var cursor = db.test.find()
> cursor.addOption
function (option) {
this._options |= option;
return this;
}
이의이 mapReduce
정의하는 방법을 살펴 보자 :
> db.test.mapReduce
function (map, reduce, optionsOrOutString) {
var c = {mapreduce:this._shortName, map:map, reduce:reduce};
...
var raw = this._db.runCommand(c);
...
return new MapReduceResult(this._db, raw);
}
는 그래서 runCommand
를 통해 명령을 실행하는 문서를 작성합니다. 더 자세히 살펴 보겠습니다.
> db.runCommand
function (obj) {
if (typeof obj == "string") {
var n = {};
n[obj] = 1;
obj = n;
}
return this.getCollection("$cmd").findOne(obj);
}
따라서 명령은 findOne
을 통해 실행됩니다. 살펴보기 :
> db.test.findOne
function (query, fields, options) {
var cursor = this._mongo.find(this._fullName, this._massageObject(query) || {}, fields, -1, 0, 0, options || this.getQueryOptions());
if (!cursor.hasNext()) {
return null;
}
var ret = cursor.next();
...
return ret;
}
아, 여기 흥미로운 것이 있습니다. 커서는 매개 변수 options
에서 오는 플래그로 초기화되는데, 이는 불행히도 runCommand
이 설정되지 않기 때문에 불행히도 도움이되지 않지만 컬렉션에서 오는 getQueryOptions()
과 OR됩니다. 조사해 보겠습니다.
> db.collection.getQueryOptions
function() {
var options = 0;
if (this.getSlaveOk()) {
options |= 4;
}
return options;
}
죄송합니다. 괜찮습니다. 따라서 우리는 커서에 접근 할 수 없으며 비 hackish 수단을 통해 실행 된 명령에 쿼리 옵션을 삽입 할 수 없습니다.
글쎄, 맵 축소 명령이 실제로 그 프로세스를 통해 서버에 전달되는 방법에 대해 많은 것을 배웠습니다. 데이터베이스의 특정 컬렉션에 대해 쿼리되는 문서 일뿐입니다. 즉, 동일한 쿼리를 작성하여 직접 실행할 수 있지만 필요한 플래그를 제공 할 수 있습니다.
전체 MongoDB 명령을 작성하고 결과를 설정하는 데 어려움은 없지만 실제로는 isMaster
명령을 사용하여 실제로 작동하는지 보여 드리겠습니다.
이
어떤 플래그없이 실행되는 명령입니다
> db.getCollection("$cmd").findOne({isMaster: 1}).ismaster
true
효과의 차이를 보려면, 우리는 데이터베이스와의 통신 tcpdump을 것입니다.우리는 관련 플래그 정수 32 비트, 바로 컬렉션 이름 앞에 살고 the wire protocol documentation에서 볼 수있는, 그래서 덤프의 관련 부분 발견하기 쉽습니다 :
. vvvvvvvvv
0x0040: d407 0000 0000 0000 7465 7374 2e24 636d ........test.$cm
0x0050: 6400 0000 0000 ffff ffff 1700 0000 0169 d..............i
좋음. 컬렉션 이름 바로 앞에 4 바이트가 0으로 표시됩니다.
이제 플래그를 제공하면서 동일한 작업을 수행해 보겠습니다. 우리는 쿼리 플래그 findOne
의 세 번째 옵션으로 제공 될 수 위의 디버깅 섹션에서 배운, 그래서 그렇게 할 수 있도록했습니다 덤프
> db.getCollection("$cmd").findOne({isMaster: 1}, undefined, 0xBEEF).ismaster
true
을 볼 : 이봐,
. vvvvvvvvv
0x0040: d407 0000 efbe 0000 7465 7374 2e24 636d ........test.$cm
0x0050: 6400 0000 0000 ffff ffff 1700 0000 0169 d..............i
우리 플래그가 전달되어야하고, 반전 된 것을 볼 수 있습니다. 즉, 바이트가 리틀 엔디안으로 인코딩되고 the docs과 일치 함을 의미합니다. 그래서
, 즉 우리가 isMaster
했던 것과 유사한 방법으로 in the documentation 설명 된대로 세 번째 findOne
의 옵션, 손으로 코드로지도-감소 명령을 플래그 DBQuery.Option.noTimeout
를 제공 할 수 있다는 것을 의미합니다, 당신은 무엇을 얻을 것이다 네가 원해.