Проверка асинхронной функции в реакции с ферментом

Несмотря на то, что вы не можете делать это в режиме реального времени, вы можете запускать несколько сокращений карт для объединения данных вместе с помощью опции «уменьшить» в MongoDB 1.8+ map / reduce (см. http: // www.mongodb.org/display/DOCS/MapReduce#MapReduce-Outputoptions). Вам нужно иметь некоторый ключ в обеих коллекциях, который вы можете использовать в качестве _id.

Например, предположим, что у вас есть коллекция users и comments, и вы хотите иметь новую коллекцию который имеет некоторую демографическую информацию пользователя для каждого комментария.

Предположим, что коллекция users имеет следующие поля:

  • _id
  • firstName
  • lastName
  • страна
  • пол
  • возраст

И тогда коллекция comments имеет следующие поля:

  • _id
  • userId
  • комментарий
  • created

Вы сделал бы это map / reduce:

var mapUsers, mapComments, reduce;
db.users_comments.remove();

// setup sample data - wouldn't actually use this in production
db.users.remove();
db.comments.remove();
db.users.save({firstName:"Rich",lastName:"S",gender:"M",country:"CA",age:"18"});
db.users.save({firstName:"Rob",lastName:"M",gender:"M",country:"US",age:"25"});
db.users.save({firstName:"Sarah",lastName:"T",gender:"F",country:"US",age:"13"});
var users = db.users.find();
db.comments.save({userId: users[0]._id, "comment": "Hey, what's up?", created: new ISODate()});
db.comments.save({userId: users[1]._id, "comment": "Not much", created: new ISODate()});
db.comments.save({userId: users[0]._id, "comment": "Cool", created: new ISODate()});
// end sample data setup

mapUsers = function() {
    var values = {
        country: this.country,
        gender: this.gender,
        age: this.age
    };
    emit(this._id, values);
};
mapComments = function() {
    var values = {
        commentId: this._id,
        comment: this.comment,
        created: this.created
    };
    emit(this.userId, values);
};
reduce = function(k, values) {
    var result = {}, commentFields = {
        "commentId": '', 
        "comment": '',
        "created": ''
    };
    values.forEach(function(value) {
        var field;
        if ("comment" in value) {
            if (!("comments" in result)) {
                result.comments = [];
            }
            result.comments.push(value);
        } else if ("comments" in value) {
            if (!("comments" in result)) {
                result.comments = [];
            }
            result.comments.push.apply(result.comments, value.comments);
        }
        for (field in value) {
            if (value.hasOwnProperty(field) && !(field in commentFields)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.users.mapReduce(mapUsers, reduce, {"out": {"reduce": "users_comments"}});
db.comments.mapReduce(mapComments, reduce, {"out": {"reduce": "users_comments"}});
db.users_comments.find().pretty(); // see the resulting collection

На этом этапе у вас будет новая коллекция под названием users_comments, которая содержит объединенные данные, и теперь вы можете ее использовать. Эти уменьшенные коллекции имеют _id, который является ключом, который вы излучали в ваших функциях карты, а затем все значения являются под-объектом внутри клавиши value - значения не находятся на верхнем уровне этих сокращенных документов .

Это несколько простой пример. Вы можете повторить это с большим количеством коллекций столько, сколько хотите продолжать наращивать уменьшенную коллекцию. Вы также можете делать сводки и агрегации данных в процессе. Вероятно, вы бы определили более одной функции сокращения, так как логика для агрегирования и сохранения существующих полей становится более сложной.

Вы также заметите, что теперь есть один документ для каждого пользователя со всеми комментариями этого пользователя в массив. Если бы мы объединили данные, которые имеют отношения «один к одному», а не «один ко многим», это было бы неплохо, и вы могли бы просто использовать функцию уменьшения следующим образом:

reduce = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};

Если вы хотите чтобы сгладить коллекцию users_comments, так что это один документ за комментарий, дополнительно выполните это:

var map, reduce;
map = function() {
    var debug = function(value) {
        var field;
        for (field in value) {
            print(field + ": " + value[field]);
        }
    };
    debug(this);
    var that = this;
    if ("comments" in this.value) {
        this.value.comments.forEach(function(value) {
            emit(value.commentId, {
                userId: that._id,
                country: that.value.country,
                age: that.value.age,
                comment: value.comment,
                created: value.created,
            });
        });
    }
};
reduce = function(k, values) {
    var result = {};
    values.forEach(function(value) {
        var field;
        for (field in value) {
            if (value.hasOwnProperty(field)) {
                result[field] = value[field];
            }
        }
    });
    return result;
};
db.users_comments.mapReduce(map, reduce, {"out": "comments_with_demographics"});

Этот метод определенно не должен выполняться «на лету». Он подходит для задания cron или что-то вроде этого, которое периодически обновляет объединенные данные. Вероятно, вы захотите запустить ensureIndex в новой коллекции, чтобы убедиться, что запросы, которые вы выполняете против этого, выполняются быстро (помните, что ваши данные все еще находятся внутри клавиши value, поэтому, если вы хотите индексировать comments_with_demographics на время комментария created, это будет db.comments_with_demographics.ensureIndex({"value.created": 1});

0
задан skyboyer 16 January 2019 в 17:22
поделиться

1 ответ

Вы можете jest.mock Keyframes. Я не уверен, откуда вы импортируете его, но если вы смоделируете все до функции загрузки и передадите шпионскую функцию next, вы можете подтвердить передачу цветов в next.

Анимации сложно проверить, и тщательное тестирование потребует много насмешек. Это не могло быть для этого.

0
ответ дан Herman Starikov 16 January 2019 в 17:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: