Pu sh Новое значение массива в документе не работает - PullRequest
0 голосов
/ 08 мая 2020

Я пытаюсь добавить новый элемент массива во внешний массив схемы, который представляет собой сериализованный трехуровневый словарь с простым объектом скаляров в качестве конечного узла. Я могу написать новый документ на втором уровне этой структуры, но не на верхнем уровне. Пример схемы приведен ниже:

"_id" : ObjectId("5eb4b4a6c0a7d49190130fcb"),
"UserId" : UUID("46b42978-29c4-4521-9832-840cead6743e"),
"Vars" : [
    {
        "k" : "LRI39",
        "v" : [
            {
                "k" : ISODate("2020-03-11T20:24:41.591Z"),
                "v" : [
                    {
                        "k" : ISODate("2020-03-11T20:24:41.594Z"),
                        "v" : {
                            "_t" : "",
                            "Source" : 1,
                            "y" : "I",
                            "ObjValue" : 19
                        }
                    }
                ]
            },
        ]
    },
}

Элемент «Vars» содержит массив документов (внешний массив) пар ключ-значение со строковым ключом (k) и значением (v) представляет собой массив документов (средний массив) пар ключ-значение с датой в качестве ключа, а значение - это еще один словарь, который не является частью этого вопроса.

Этот код оболочки mon go работает ( для ясности, RC22 не существует как элемент массива Vars при его вызове)

db.threetier.update(
    { UserId: UUID("46b42978-29c4-4521-9832-840cead6743e")},
    { $push: 
        { "Vars": 
            { "k": "RC22",
              "v" : [       
                    {   "k" : ISODate("2020-04-02T10:11:12Z"),
                        "v" : [ 
                            { "k" : ISODate("2020-04-02T10:11:12Z"),
                              "v" : { 
                                    "y": "I",
                                    "Source" : 1,
                                    "ObjValue" : "Flooby"
                                }
                            }
                        ]
                    }
                ]
            }
        }
    },
    { upsert: true }
);

Однако этот C# код не существует: я получаю InvalidCastException. gUserId - это Guid, который соответствует полю UserId документа.

NewItem = new BsonDocument()
    {
        { "k", "RC22" },
        { "v", new BsonArray
            { new BsonDocument
                {
                    { "k", DateTime.Now },
                    { "v", new BsonArray
                        { new BsonDocument()
                            {
                                { "k", DateTime.Now },
                                { "v", new BsonDocument()
                                    {
                                        { "y", "I" },
                                        { "Source", 1 },
                                        { "ObjValue", "Flooby" }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    };

Filter = Builders<UserData>.Filter.Eq("UserId", gUserId);

// Create the update document
Update = Builders<UserData>.Update.Push("Vars", NewItem);

UpdateOptions Options = new UpdateOptions() { IsUpsert = true };

// Execute the update
UpdateResult urResult = _imcCollUserData.UpdateOne(Filter, Update, Options);

Теперь этот код C# отлично работает для обновления второго уровня структуры (LRI39 существует как элемент верхнего уровня array):

NewItem = new BsonDocument
    {
        { "k", DateTime.Now },
        { "v", new BsonArray
            { new BsonDocument()
                {
                    { "k", DateTime.Now },
                    { "v", new BsonDocument()
                        {
                            { "y", "I" },
                            { "Source", 1 },
                            { "ObjValue", "Flooby" }
                        }
                    }
                }
            }
        }
    };

Filter = Builders<UserData>.Filter.Eq("UserId", gUserId) &
            Builders<UserData>.Filter.Eq("Vars.k", "LRI39");

// Create the update document
Update = Builders<UserData>.Update.Push("Vars.$.v", NewItem);

UpdateOptions Options = new UpdateOptions() { IsUpsert = true };

// Execute the update
UpdateResult urResult = _imcCollUserData.UpdateOne(Filter, Update, Options);

Нет другой информации, кроме недопустимого исключения приведения (например, имени поля или чего-то еще), с трассировкой стека:

at MongoDB.Bson.Serialization.Serializers.SerializerBase`1.MongoDB.Bson.Serialization.IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
at MongoDB.Driver.PushUpdateDefinition`2.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.MongoCollectionImpl`1.ConvertWriteModelToWriteRequest(WriteModel`1 model, Int32 index)
at System.Linq.Enumerable.<SelectIterator>d__5`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation..ctor(CollectionNamespace collectionNamespace, IEnumerable`1 requests, MessageEncoderSettings messageEncoderSettings)
at MongoDB.Driver.MongoCollectionImpl`1.CreateBulkWriteOperation(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options)
at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass23_0.<BulkWrite>b__0(IClientSessionHandle session)
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionBase`1.<>c__DisplayClass98_0.<UpdateOne>b__0(IEnumerable`1 requests, BulkWriteOptions bulkWriteOptions)
at MongoDB.Driver.MongoCollectionBase`1.UpdateOne(FilterDefinition`1 filter, UpdateDefinition`1 update, UpdateOptions options, Func`3 bulkWrite)
at MongoDB.Driver.MongoCollectionBase`1.UpdateOne(FilterDefinition`1 filter, UpdateDefinition`1 update, UpdateOptions options, CancellationToken cancellationToken)

Я посмотрел в журнале драйвера, и нет информации об этой ошибке, даже если ведение журнала установлено на подробный (5). Google очень мало возвращает для недопустимых приведений, большинство из которых связано с проблемами ObjectId. Я не могу отследить код сериализации, поэтому не уверен, что именно вызывает сбой. BsonDocument мне кажется точным воспроизведением работающей команды оболочки mon go. Я подозреваю, что спецификация целевого поля неверна, но использование Vars. $ Или Vars.0 возвращает ошибку «Сериализатор для поля 'Vars.0' [или Vars. $] Должен реализовать IBsonArraySerializer и предоставить информацию о сериализации элемента».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...