Как обновить свойство в нескольких объектах в массиве для одного документа в коллекции Meteor /minimongo?
Мой вопрос почти дубликат этого вопроса. Разница в том, что я использую минимонго в рамках / платформе Meteor. Учитывая этот документ:
{
"_id" : ObjectId("4d2d8deff4e6c1d71fc29a07"),
"user_id" : "714638ba-2e08-2168-2b99-00002f3d43c0",
"events" : [
{
"handled" : {
"name": "Mike",
"visible": false
},
"profile" : 10,
"data" : "....."
}
{
"handled" : {
"name": "Shaun",
"visible": false
},
"profile" : 10,
"data" : "....."
}
{
"handled" : {
"name": "Glen",
"visible": true
},
"profile" : 20,
"data" : "....."
}
]}
Как мне запросить конкретный user
а также update
все объекты в массиве событий ТОЛЬКО где 'handled.visible':false to 'handled.visible':true
? Насколько это возможно, я бы хотел, чтобы это было в одном запросе. Моя цель действительно улучшить производительность моего приложения. Вместо того, чтобы извлекать весь массив объектов, обрабатывать их на стороне клиента (изменять свойства объекта), а затем повторно обновлять на сервере, было бы здорово обновить напрямую через Mongo. Изменение данных непосредственно на сервере также является изначально реагирующим и выгодным, хотя на самом деле не является необходимым для моего приложения.
Я не совсем уверен, как сформулировать запрос в минимонго.
Я пытался:
Meteor.users.update({_id: 's8Ppj4ZFSeq9X6xC4', 'events.handled.visible': false }, { $set:{'events.$.handled.visible':true} });
Это работало только для первого объекта, найденного в массиве. Однако я хотел бы обновить все объекты в массиве, где handled.visible имеет значение false.
3 ответа
Вы можете создать метод сервера, который использует структуру агрегации для возврата счетчика, который вы можете использовать в своем клиенте в качестве цикла для обновления каждого соответствующего элемента массива. В следующем непроверенном примере могут быть некоторые указания о том, как вы можете это сделать (я не проверял это, поэтому отзывы о вашей реализации приветствуются, чтобы сделать это лучшим решением):
Сервер:
Добавьте пакет meteorhacks: агрегат в ваше приложение с
meteor add meteorhacks:aggregate
а затем использовать как
Meteor.methods({
getInvisibleEventsCount: function(userId){
var pipeline = [
{ "$match": { "_id": userId, "events.handled.visible": false } },
{ "$unwind": "$events.handled" },
{ "$match": { "events.handled.visible": false } },
{ "$group": {
"_id": null,
"count": { "$sum": 1 }
}}
];
var result = Meteor.users.aggregate(pipeline);
return result;
}
});
Клиент:
Meteor.call("getInvisibleEventsCount", userId, function(err, response) {
var max = response[0].count;
while(max--) {
Meteor.users.update(
{ "_id": userId, "events.handled.visible": false },
{ "$set": { "events.$.handled.visible": true} }
);
}
});
Метеор в настоящее время не позволяет обновлять несколько элементов в массиве. Необходимо обновить массив для обновления для каждого возвращенного документа.
До сих пор я пробовал 3 метода, один из которых опубликован chridam, который работает.
Метод 1 просто обрабатывает его в клиенте, но выборочно выбирает только ложные записи:
testLocalAggregate : function(){
var findQuery = Meteor.users.findOne(Meteor.userId(), {fields:{'events':1}}).events;
var tempArr = [];
_.each(findQuery, function(event, index){
if(events.handled.visible === false){
tempArr.push(index);
}
});
if(tempArr.length){
var count = tempArr.length;
while(count --){
Meteor.users.update(
{ "_id": Meteor.userId(), "events.handled.visible": false },
{$set:{'events.$.handled.visible':true}}
);
}
}
}
Метод 2 заключается в замене всех записей независимо от того, является ли истина или ложь, что является самым простым и простым (я знаю, что я указал в своем вопросе только обновление ложных записей, но для повышения производительности это решение также представлено).
testUpdate : function(){
var events = Meteor.users.findOne(Meteor.userId(), {fields:{'events':1}}).events;
_.each(events, function(event, index){
if(events.handled.visible === false){
events.handled.visible = true;
}
});
Meteor.users.update({_id : Meteor.userId()}, {$set: {'events': events}});
}
Согласно тестированию в Kadira с 5 вызовами методов, средняя пропускная способность и время отклика следующие:
Способ 1:
Средняя пропускная способность - .08/ мин
Среднее время отклика - 219 мс
Способ 2:
Средняя пропускная способность - .12/ мин
Среднее время отклика - 109мс
Метод Chridam:
Средняя пропускная способность - .08/ мин
Среднее время отклика - 221 мс
Способ 1 и Chridam's почти одинаковы. Но я заметил, что обновления пользовательского интерфейса быстрее, используя метод 2, с сопоставимой пропускной способностью и временем отклика. Я просто не уверен, что метод 2 будет лучше, так как выполняется больше вызовов метода.
Будем очень благодарны за любые комментарии по улучшению опубликованных методов или которые могут быть быстрее в других обстоятельствах.