Обновить документ монго как целое или определенные поля - PullRequest
1 голос
/ 21 июня 2019

Сценарий

У меня есть документ беседы в mongodb, я должен добавить сообщения в массив сообщений и обновить дату последней отправки, см. Схему ниже.

{ 
"_id" : NumberInt(5), 
"CurrentOwnerId" : NumberInt(9), 
"LastSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
"Messages" : [
    {
        "_id" : BinData(3, "nuC1iYTKtkGzSuv7pVHsKg=="), 
        "MessageContent" : "Hi There", 
        "Status" : "Pending", 
        "DateSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
        "Method" : "Slack"
    }
 ]
}

Мой вопрос

Было бы эффективнее просто прочитать весь документ (используя BsonId) и обновить документ с помощью c # в целом, т.е. отправить мое сообщение намассив и установка последнего отправленного дня, а затем обновление документа в целом с помощью драйвера ИЛИ два вызова базы данных с использованием операторов $ set и $ push для достижения того, что я хочу сделать.

Ответы [ 3 ]

1 голос
/ 21 июня 2019

Как сказал Эдуардо Хитек, вы можете установить несколько свойств в одном запросе.Таким образом, вы можете обновить сущность без необходимости сначала извлекать ее из базы данных следующим образом:

    //Build an Id Filter
    var idFilter = Builders<Chat>.Filter.Eq(x => x.Id, "1");


    var message = new Message() { MessageContent = "Hey!", Method = "Slack" };

    //Build an update definition to add the message
    var addMessage = Builders<Chat>.Update.AddToSet(x => x.Messages, message);
    //Build an update definition to set the LastSent property
    var setLastSent = Builders<Chat>.Update.Set(x => x.LastSent, DateTime.Now);
    //Combine both update definitions
    var combinedUpdate = Builders<Chat>.Update.Combine(addMessage, setLastSent);

    //Execute the query.
    db.GetCollection<Chat>("ChatCollection").UpdateOne(idFilter, combinedUpdate);

Дополнительным преимуществом обновления сущности, подобной этой, является то, что она выполняется атомарно.

1 голос
/ 21 июня 2019

Я думаю, вам не нужно делать 2 вызова, потому что команда обновления MongoDB может принять более одной инструкции по обновлению.Пример:

db.collection.update({_id: docId}, {$push: {values: dboVital}, $set: {endTime: time}});

Итак, вы можете добавить сообщение в ваш массив и обновить lastSentDay всего одним вызовом.

0 голосов
/ 21 июня 2019

Как и в других ответах, вы можете сделать это с помощью одной команды mongodb с помощью $ push или $ addToSet.Вот как это сделать удобным и строго типизированным способом, используя мою библиотеку MongoDB.Entities

using MongoDB.Entities;
using System;

namespace StackOverflow
{
    public class Program
    {
        public class Conversation : Entity
        {
            public DateTime LastSent { get; set; }
            public Message[] Messages { get; set; }
        }

        public class Message
        {
            public string Content { get; set; }
        }

        private static void Main(string[] args)
        {
            new DB("test");

            var convo = new Conversation
            {
                LastSent = DateTime.Now.AddMinutes(-10),
                Messages = new[] { new Message { Content = "This is the first message..." } }
            };
            convo.Save();

            var msg = new Message { Content = "This is a new message..." };

            DB.Update<Conversation>()
              .Match(c => c.ID == convo.ID)
              .Modify(c => c.LastSent, DateTime.Now)
              .Modify(b => b.Push(c => c.Messages, msg))
              .Execute();
        }
    }
}

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

db.Conversation.update(
    {
        "_id": ObjectId("5d0ce23647e2d210903b3930")
    },
    {
        "$set": {
            "LastSent": ISODate("2019-06-21T13:57:10.998Z")
        },
        "$push": {
            "Messages": {
                "Content": "This is a new message..."
            }
        }
    },
    {
        "multi": true,
        "upsert": false
    }
)
...