繁体   English   中英

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

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

我正在运行下面的代码并收到后续错误:

码:

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" });
        }
    }
}

错误:

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

可以注意到,主程序中有一些控制操作,这些操作表明可以将数据插入到目标DB中,并且可以在BulkWrite()操作中插入包含有问题的子字符串的BulkWrite() 我正在针对4.0.0版的MongoDB进行测试,并使用2.7.0版的官方Mongo C#驱动程序进行测试。

BulkWrite()操作之前,有人会知道我在准备数据(例如转义)方面会缺少什么吗? 确切地说,在'\\'解决问题之前应用另一对'\\'(因此, Nick\\\\1变为Nick\\\\\\\\1 )。 但是我感觉这有点棘手,因为可能还会有其他情况破坏序列化过程。 因此,我希望SDK可以提供一个“转义函数”或“包装对象”,以便解决这些序列化陷阱。

如果您自己在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)");
    }

它将正确地转义字符。

而且,如果您想知道驱动程序是如何执行的,则可以在此处看到此情况: 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