简体   繁体   English

MongoDB中的BulkWrite操作因无效的转义序列而失败

[英]BulkWrite operation in MongoDB failing with invalid escape sequence

I am running the code below and receiving the subsequent error: 我正在运行下面的代码并收到后续错误:

Code: 码:

using MongoDB.Bson;
using MongoDB.Driver;
using System.Collections.Generic;

namespace MongoBulkWriteSerializationFailure
{
    class Person
    {
        public string Firstname;
        public string Lastname; 
    }

    class DummyClient
    {
        private IMongoCollection<BsonDocument> _collection;

        public DummyClient()
        {
            _collection = (new MongoClient("mongodb://root:password@localhost:27017/")).GetDatabase("my_db").GetCollection<BsonDocument>("persons");
        }

        public void Upsert(Person person)
        {
            List<WriteModel<BsonDocument>> list_of_operations = new List<WriteModel<BsonDocument>>();
            ReplaceOneModel<BsonDocument> write_model = new ReplaceOneModel<BsonDocument>($"{{ 'firstname': '{person.Firstname}', 'lastname': '{person.Lastname}'}}", person.ToBsonDocument());
            write_model.IsUpsert = true;
            list_of_operations.Add(write_model);
            BulkWriteResult<BsonDocument> outcome = _collection.BulkWrite(list_of_operations, new BulkWriteOptions { IsOrdered = false });
            System.Console.WriteLine($"Processed {outcome.ProcessedRequests.Count} item(s)");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            DummyClient client = new DummyClient();

            // Successful Control test:
            ((new MongoClient("mongodb://root:password@localhost:27017/")).GetDatabase("my_db").GetCollection<BsonDocument>("persons")).InsertOne((new Person { Firstname = "John\\1", Lastname = "Smith" }).ToBsonDocument());

            // Successful operation:
            client.Upsert(new Person { Firstname = "Mike", Lastname = "Smith" });

            // Failing operation:
            client.Upsert(new Person { Firstname = "Nick\\1", Lastname = "Smith" });
        }
    }
}

Error: 错误:

System.FormatException
  HResult=0x80131537
  Message=Invalid escape sequence in JSON string '\1'.
  Source=MongoDB.Bson
  StackTrace:
   at MongoDB.Bson.IO.JsonScanner.GetStringToken(JsonBuffer buffer, Char quoteCharacter)
   at MongoDB.Bson.IO.JsonScanner.GetNextToken(JsonBuffer buffer)
   at MongoDB.Bson.IO.JsonReader.PopToken()
   at MongoDB.Bson.IO.JsonReader.ReadBsonType()
   at MongoDB.Bson.Serialization.Serializers.BsonDocumentSerializer.DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args)
   at MongoDB.Bson.Serialization.Serializers.BsonValueSerializerBase`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
   at MongoDB.Bson.BsonDocument.Parse(String json)
   at MongoDB.Driver.JsonFilterDefinition`1.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(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 MongoBulkWriteSerializationFailure.DummyClient.Upsert(Person person) in C:\code\MongoBulkWriteSerializationFailure\Program.cs:line 28
   at MongoBulkWriteSerializationFailure.Program.Main(String[] args) in C:\code\MongoBulkWriteSerializationFailure\Program.cs:line 46

As it would be noted there are some control operations in the main program which demonstrate that data can be inserted in the target DB as well as data that contains the offending sub-string in the BulkWrite() operation. 可以注意到,主程序中有一些控制操作,这些操作表明可以将数据插入到目标DB中,并且可以在BulkWrite()操作中插入包含有问题的子字符串的BulkWrite() I am testing against version 4.0.0 of MongoDB and using version 2.7.0 of the official Mongo C# driver. 我正在针对4.0.0版的MongoDB进行测试,并使用2.7.0版的官方Mongo C#驱动程序进行测试。

Would anyone know what I could be missing in terms of preparing the data (eg escaping) prior to the BulkWrite() operation? BulkWrite()操作之前,有人会知道我在准备数据(例如转义)方面会缺少什么吗? To be precise, applying another pair of '\\' before the '\\' solves the problem (so, Nick\\\\1 becomes Nick\\\\\\\\1 ). 确切地说,在'\\'解决问题之前应用另一对'\\'(因此, Nick\\\\1变为Nick\\\\\\\\1 )。 But I have a feeling that this is a bit hacky as there could be other corner-cases that would break the serialization process. 但是我感觉这有点棘手,因为可能还会有其他情况破坏序列化过程。 So, I am hoping that there is an 'escape function' or 'wrapper object' provided by the SDK that could be leveraged in order to address these serialization traps. 因此,我希望SDK可以提供一个“转义函数”或“包装对象”,以便解决这些序列化陷阱。

If you build the FilterDefinition yourself in the Upsert function like this: 如果您自己在Upsert函数中构建FilterDefinition ,如下所示:

  public void Upsert(Person person)
    {
        var fiterBuilder = Builders<BsonDocument>.Filter;

        var escapedFirstname = filter_builder.Eq("Firstname", person.Firstname);
        var escapedLastname = filter_builder.Eq("Lastname", person.Lastname);

        var filter = fiterBuilder.And(escapedFirstname, escapedLastname);

        List<WriteModel<BsonDocument>> list_of_operations = new List<WriteModel<BsonDocument>>();
        ReplaceOneModel<BsonDocument> write_model = new ReplaceOneModel<BsonDocument>(filter, person.ToBsonDocument());
        write_model.IsUpsert = true;
        list_of_operations.Add(write_model);
        BulkWriteResult<BsonDocument> outcome = _collection.BulkWrite(list_of_operations, new BulkWriteOptions { IsOrdered = false });
        System.Console.WriteLine($"Processed {outcome.ProcessedRequests.Count} item(s)");
    }

It will escape the characters correctly. 它将正确地转义字符。

And if you wish to know how the Driver does this you can see this happen here: https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Bson/IO/JsonScanner.cs#L33 而且,如果您想知道驱动程序是如何执行的,则可以在此处看到此情况: https : //github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Bson/IO/JsonScanner.cs# L33

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM