Гибкие функции JavaScript (для MongoDB) - PullRequest
1 голос
/ 16 сентября 2010

Я работаю над некоторыми запросами Map / Reduce для MongoDB и пытаюсь сделать следующее (в двух словах).

m = function()
{
    this.convert = function(val)
    {
        return val+1;
    }

    emit(convert(this.age), this.doesWearGlasses);
}

r = function(k, v)
{
    count = 0;
    for(var i = 0; i < v.length; i++)
    {
        count += v[i];
    }
    return count;
}

if(tuned)
{
    m.convert = function(val)
    {
        return val;
    }
}

/**
* Continue to running the M/R query
*/

Следует отметить, что я пишу это как приложение Node.js, но я предполагаю, что большинство тех же принципов применимы к любому JavaScript.

Проблема в том, что я не думаю, что смогу изменить его, не создав объект, аля mTmp = new m();, однако не могу, потому что emit() (и все остальное) не определено.

Я пытался использовать m.prototype.convert = function, но это не работает. Значение m.toString() не изменяется.

Ответы [ 2 ]

1 голос
/ 28 января 2012

I думаю, , что вы пытаетесь частью m (функция карты), ведут себя по-разному, в зависимости от того, установлен ли tuned. Это верно?

К сожалению, поскольку функции преобразования и сокращения передаются в MongoDB в виде строк, содержащих только тела функций, они не будут иметь доступа к какому-либо внешнему коду или данным - поэтому любые свойства, которые вы задали для функции, просто победили ' быть там, когда он будет выполнен.

Если я правильно вас понимаю, я думаю, что это три ваших лучших варианта:

  1. Определите разные версии m для каждого случая.

  2. Соберите m в виде строки, вставляя в правую часть кода в зависимости от значения tuned.

  3. Заставьте m решить, как вести себя на основе переменной, например:

    m = function()
    {
        var result;
        if (tuned) {
            result = this.age;
        } else {
            result = this.age + 1;
        }
        emit(convert(this.age), this.doesWearGlasses);
    }
    

    … и дайте переменной tuned вторую жизнь внутри MongoDB при вызове mapReduce:

    collection.mapReduce(m, r, { scope: { tuned: tuned } });
    

    (FWIW, если разница, на самом деле, такая простая, вы можете написать m вот так:)

    m = function()
    {
        emit(convert(tuned ? this.age : this.age + 1), this.doesWearGlasses);
    }
    

... дайте мне знать, если вы имеете в виду что-то другое.

0 голосов
/ 16 сентября 2010

Поскольку вы вызываете конструктор после определения функции prototype, this.convert перезапишет уже определенную функцию-прототип.

Вы можете переписать весь конструктор m:

m = function()
{
    this.convert = function(val)
    {
        return val+1;
    }
}

if(tuned) {
    m = (function(mOld) {
        return function()
        {
            mOld.apply(this, arguments);
            this.convert = function(val){ return val; }
        }
    })(m);
}

// Test code
function doStuff(obj) {
    alert(obj.toString());
}

var mObj = new m();
doStuff(mObj);

Это должно сработать, но я не знаю, что еще может повлиять на ваш настоящий сценарий.

Обратите внимание, что используется шаблон self-invocation , который создает замыкание.

Я добавил тестовый код, который демонстрирует, что это работает с учетом ограничений в OP.

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