MongoDB / PyMongo: Как использовать точечную запись в функции Map? - PullRequest
6 голосов
/ 08 июля 2011

Я пытаюсь подсчитать, сколько записей я нашел в каждом почтовом индексе.
В моем MongoDB встроен почтовый индекс;используя точечную запись, он расположен по адресу a.res.z (адрес для адреса, адрес для проживания, z для почтового индекса).Например, это прекрасно работает:

db.NY.count({'a.res.z' : '14120'})

Но когда я пробую функцию карты (в python, потому что я использую PyMongo):

map = Code("function () {"
           "    emit(this.a.res.z, 1);"
           "}")

Я получаю эту ошибку, когдаЯ называю mapreduce:

pymongo.errors.OperationFailure: db assertion failure, assertion: 'map invoke failed: JS Error: TypeError: this.a has no properties nofile_b:0', assertionCode: 9014

Точечная запись работает на верхнем уровне - например, одна точка - но я не могу заставить ее работать со встроенными.В чем секрет?

1 Ответ

9 голосов
/ 08 июля 2011

Эта ошибка означает, что по крайней мере один объект, уменьшающий карту, пропускает поле res своего a.См .:

> db.NY.find({}, {_id: 0})                                             
{ "a" : { "res" : { "z" : 10011 } }, "name" : "alice" }
{ "a" : { "res" : { "z" : 10011 } }, "name" : "bob" }
{ "a" : { "res" : { "z" : 10012 } }, "name" : "carol" }
> m                                                                    
function () {
    emit(this.a.res.z, 1);
}
> r                                                                    
function (key, values) {
    var v = 0;
    values.forEach(function (obj) {v += obj;});
    return v;
}
> db.runCommand({mapreduce: "NY", map: m, reduce: r, out: {inline: 1}})
{
    "results" : [
        {
            "_id" : 10011,
            "value" : 2
        },
        {
            "_id" : 10012,
            "value" : 1
        }
    ],
    "timeMillis" : 0,
    "counts" : {
        "input" : 3,
        "emit" : 3,
        "output" : 2
    },
    "ok" : 1
}
> db.NY.insert({a: {}, name: "empty"})                                                       
> db.runCommand({mapreduce: "NY", map: m, reduce: r, out: {inline: 1}})
{
    "assertion" : "map invoke failed: JS Error: TypeError: this.a.res has no properties nofile_b:1",
    "assertionCode" : 9014,
    "errmsg" : "db assertion failure",
    "ok" : 0
}

. Вы можете использовать аргумент query, чтобы преобразовать карту, чтобы работать только с теми, у которых есть нужные поля:

> db.runCommand({mapreduce: "NY", map: m, reduce: r, out: {inline: 1},
                 query: {"a.res.z": {$exists: true}}})
{
    "results" : [
        {
            "_id" : 10011,
            "value" : 2
        },
        {
            "_id" : 10012,
            "value" : 1
        }
    ],
    "timeMillis" : 1,
    "counts" : {
        "input" : 3,
        "emit" : 3,
        "output" : 2
    },
    "ok" : 1
}

Для использования query аргумент от PyMongo, вы можете установить его в качестве ключевого аргумента на map_reduce(...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...