Mongoose: Как заменить массив вложенных документов?

Я настроил пользовательскую схему с мангустом, которая содержит вложенный документ «контакты». Поддокумент «Контакты» представляет собой набор объектов контактов, которые содержат фактический контакт (ссылка на другой пользовательский объект) и некоторые данные, связанные с «дружбой».

В моем внешнем приложении теперь я могу управлять контактами, добавляя или удаляя пользователей в свой список контактов. Внешний интерфейс сохраняет эти изменения как HTTP-запросы PUT на сервер.

Запрос PUT содержит весь пользовательский объект, который более или менее заменяет пользовательский объект в базе данных. К сожалению, заменить коллекцию поддокументов невозможно. Вы можете только добавлять новые или удалять их.

Вот схемы:

var UserSchema = new Mongoose.Schema({

    username: { 
        type: String, 
        index: { unique: true, sparse: true }, 
        required: true, lowercase: true, trim: true
    },

    email: {
        type: String,
        index: { unique: true, sparse: true }, 
        required: true, lowercase: true, trim: true
    },

    contacts: [ContactSchema]

});

var ContactSchema = new Mongoose.Schema({

    user: {
        ref: "User",
        type: Mongoose.Schema.ObjectId
    },

    isContact: {
        type: Boolean,
        default: true
    }

});

В настоящее время я пытаюсь заменить контакты, удалив все и добавив один в запросе:

app.put('/me', loadUser, function(req, res, next) {
    var user = req.user;

    req.user.contacts.forEach(function(contact) {
        req.body.contacts.forEach(function(contact) {
            contact.remove();
        });
    });

    req.body.contacts.forEach(function(contact) {
        req.user.contacts.push(contact);
    });

    user.save(function(err, user) {
        if (err) return next(err);
        res.send(200);
    });
});

Есть ли у кого-нибудь лучшее представление о том, как я могу обновить эту коллекцию вложенных документов до состояния в запросе?


person bodokaiser    schedule 18.11.2012    source источник
comment
Когда вы получаете весь пользовательский объект, вы не можете просто сохранить весь объект в монго? если вы заменяете тот же документ одним и тем же _id, он должен перезаписать его   -  person Gianfranco P.    schedule 20.11.2012


Ответы (1)


Вы можете использовать библиотеку _underscore для фильтрации (отклонения) объекта, который хотите удалить.

Вот пример, как удалить что-то из массива без foreach.

var _und = require('underscore');

var array = [{_id:1, title:'object one'}, {_id:2, title:'object two'}, {_id:3, title: 'object three' }]
    the_target = 'object two';
    new_array = _und.reject(array, function(item){
       return item.title === target;
    })

Ожидаемый результат должен быть:

=> [{_id:1, title:'object one'}, {_id:3, title:'object three'}]

Если вы знаете идентификатор, даже лучше.

Все, что вам нужно сделать, это очистить ваши поддокументы, выполнив следующие действия:

var mytargetarray = [];
    mytargetarray.push(new_array);
    mytargetarray.save();

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

req.user.contacts = [];
req.user.contacts.push(req.body.contacts);

сохранить и готово.

Надеюсь, это немного поможет.

Просто подсказка, в mongodb вы работаете с массивами объектов, вы можете просто заменить каждое значение:

// active data from database
user.name = 'test user';
// now just give the object a new value
user.name = 'new name';
// and save .. done
user.save();
person Daniel    schedule 23.11.2012
comment
небольшое редактирование: req.user.contacts.push(req.body.contacts); // разве это не создает equals [[contacts]] ? - person daedelus_j; 11.12.2012
comment
только если вы нажимаете массив, а не массив объектов. так как для этого примера лучше всего было бы снова использовать подчеркивание. есть несколько команд, таких как _.union(array1, array2) .. которые также сравнивают 2 массива на наличие повторяющихся записей. если вы остаетесь в одном и том же контексте, вы должны быть осторожны с дублированием массива снова и снова. Я действительно больше не использую push массива, потому что вы никогда не знаете, куда и что вы нажимаете..;) - person Daniel; 20.02.2013