Обновление данных встроенного документа в MongoDB

7

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

{ "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" }, 
"companies" : 
  [
    { "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" },
       "name" : "Google" },
    { "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" }, 
       "name" : "Greenfin" }, 
    { "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" },
       "name" : "Zynet"   }
 ],
 "firstname" : "Peter", 
 "surname" : "Smith" }

(т.е. документ Person с массивом Companies, встроенным в документ человека), то как мне обновить ВСЕ вхождения определенной компании (цель через компанию _id) с помощью одного запроса + обновление?

Я пробовал следующее:

MongoCollection personCollection = mdb.GetCollection("person");
BsonBinaryData bin = new BsonBinaryData(new Guid("0AE91D6B-A8FA-4D0D-A94A-91D6AC9EE343"));
QueryComplete query = Query.EQ("companies._id", bin);
var update = Update.Set("companies.name", "GreenfinNewName");
SafeModeResult result = personCollection.Update(query, update, UpdateFlags.Multi);

но это не сработает. Думаю, мой вопрос сводится к двум вопросам: как настроить таргетинг на встроенные компании в исходный запрос, а затем как установить новое название компании в инструкции Set. Примечание. В этом примере я решил "денормализовать" данные компании и вставить ее в документ каждого человека, поэтому может быть несколько документов с одинаковым идентификатором и именем компании. Большое спасибо.

UPDATE: Используя технику Bugai13, я стал ближе. Это работает:

MongoCollection personCollection = mdb.GetCollection("person");
QueryComplete query = Query.EQ("companies.name", "Bluefin");
var update = Update.Set("companies.$.companynotes", "companynotes update via name worked");
SafeModeResult result = personCollection.Update(query, update, UpdateFlags.Multi, SafeMode.True);

Но это не работает:

MongoCollection personCollection = mdb.GetCollection("person");
BsonBinaryData bin = new BsonBinaryData(new Guid("0AE91D6B-A8FA-4D0D-A94A-91D6AC9EE343"));
Builders.QueryComplete query = Query.EQ("companies._id", bin);
var update = Update.Set("companies.$.companynotes", "companynotes update via id worked");
SafeModeResult result = personCollection.Update(query, update, UpdateFlags.Multi, SafeMode.True);

Итак, я пока не могу обновить с использованием первичного ключа, что мне нужно сделать...

Теги:

2 ответа

9
Лучший ответ

Полагаю, вы должны взглянуть на оператор позиционирования в mongodb:

var update = MongoDB.Driver.Builders.Update
                                 .Set("companies.$.name", "GreenfinNewName");
                                                 ^^
                                            all magic here

Примечание: выше код обновит только first согласованный элемент в массиве. Поэтому, если у вас есть две компании в вложенном массиве с name = GreenfinNewName выше, код будет обновляться только с первого раза.

Примечание: UpdateFlags.Multi означает несколько документов, но не несколько элементов в вложенном массиве.

Update:

QueryComplete query = Query.EQ("companies._id", 
    BsonValue.Create(new Guid("0AE91D6B-A8FA-4D0D-A94A-91D6AC9EE343")));
var update = Update.Set("companies.$.companynotes", "companynotes");
personCollection.Update(query, update, UpdateFlags.Multi, SafeMode.True);

Надеюсь на эту помощь!

  • 0
    Большое спасибо, это сблизило меня. Использование вашей техники позволяет мне обновляться на основе текстового значения в массиве, но не на главном ключе _id. Я уточню вопрос с деталями ...
  • 0
    @JohnNorris: Конечно, обновите свой вопрос, и я постараюсь вам помочь. Ожидание ..
Показать ещё 2 комментария
0

Просто хотел сказать спасибо вам обоим. Изучение Mongo и этой нити помогло.

Я использую драйвер 10gen С#, и для справки это мой код:

        MongoServer mongo = MongoServer.Create();

        MongoDatabase db = mongo.GetDatabase("test");

        MongoCollection<BsonDocument> coll = db["contacts"];

        BsonDocument doc = new BsonDocument();

        doc["FirstName"] = "Daniel";
        doc["LastName"] = "Smith";
        doc["Address"] = "999 Letsby Avenue";
        doc["City"] = "London";
        doc["County"] = "Greater London";
        doc["Postcode"] = "N13";

        coll.Insert<BsonDocument>(doc);

        QueryComplete qSel = Query.EQ("Postcode", "N13");

        MongoCursor<BsonDocument> cur = coll.Find(qSel);
        foreach (BsonDocument bdoc in cur)
        {
            Console.WriteLine(bdoc["FirstName"] + ":" + bdoc["Address"]);
        }


        UpdateBuilder docTwo = Update.Set("Postcode", "MK10");

        coll.Update(qSel, docTwo, UpdateFlags.Multi);

        QueryDocument qSel2 = new QueryDocument("FirstName", "Daniel");

        MongoCursor<BsonDocument> cur2 = coll.Find(qSel2);
        foreach (BsonDocument bsdoc in cur2)
        {
            Console.WriteLine(bsdoc["FirstName"] + " : " + bsdoc["Postcode"]);
        }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню