using System.Text.Json;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Bson.Serialization;
using BsonExtensions.Converters;
using System.Linq.Expressions;
namespace BsonExtensions;
public static class BsonJsonExtensions
{
///
/// Add BsonDocumentJsonConverter and BsonDocumentsJsonConverter to IMvcCoreBuilder
///
///
///
public static IMvcCoreBuilder AddBsonJsonConverters(this IMvcCoreBuilder builder)
{
return builder.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new BsonDocumentJsonConverter());
options.JsonSerializerOptions.Converters.Add(new BsonDocumentsJsonConverter());
options.JsonSerializerOptions.DictionaryKeyPolicy = null;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
}
public async static Task RunCommandAsync(this IMongoDatabase db, string JsonDocument, ReadPreference? readPreference = null, CancellationToken cancellationToken = default)
{
return await db.RunCommandAsync(BsonDocument.Parse(JsonDocument), readPreference, cancellationToken);
}
public async static Task InsertOneAsync(this IMongoCollection collection, string Json, InsertOneOptions? options = null, CancellationToken cancellationToken = default)
{
var doc = BsonDocument.Parse(Json);
await collection.InsertOneAsync(doc, options, cancellationToken);
return doc["_id"];
}
public async static Task InsertOneAsync(this IMongoCollection collection, object objA, InsertOneOptions? options = null, CancellationToken cancellationToken = default)
{
var doc = BsonJsonSerializer.ToBsonDocument(objA);
await collection.InsertOneAsync(doc, options, cancellationToken);
return doc["_id"];
}
public async static Task> InsertManyAsync(this IMongoCollection collection, string JsonDocuments, InsertManyOptions? options = null, CancellationToken cancellationToken = default)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
await collection.InsertManyAsync(bsonDocuments, options, cancellationToken);
return bsonDocuments.Select(x => x["_id"]).ToList();
}
public async static Task ReplaceOneByIdAsync(this IMongoCollection collection, object objA, CancellationToken cancellationToken = default)
{
var doc = BsonJsonSerializer.ToBsonDocument(objA);
var id = doc["_id"];
string filter;
if (id.IsGuid)
filter = $"{{ _id : UUID('{id.AsGuid}') }}";
else if (id.IsObjectId)
filter = $"{{ _id : ObjectId('{id.AsObjectId}') }}";
else if (id.IsString)
filter = $"{{ _id : '{id.AsString}' }}";
else
filter = $"{{ _id : {id.AsInt64} }}"; // some kind of int
return await collection.ReplaceOneAsync(filter, doc, new ReplaceOptions() { IsUpsert = true }, cancellationToken);
}
public async static Task UpdateOneAsync(this IMongoCollection collection, string Json, T? objA, UpdateOptions? updateOptions = null, CancellationToken cancellationToken = default)
{
if (objA == null)
throw new Exception("update object is null");
var doc = BsonJsonSerializer.ToBsonDocument(objA);
var id = doc["_id"];
string filter;
if (id.IsGuid)
filter = $"{{ _id : UUID('{id.AsGuid}') }}";
else if (id.IsObjectId)
filter = $"{{ _id : ObjectId('{id.AsObjectId}') }}";
else if (id.IsString)
filter = $"{{ _id : '{id.AsString}' }}";
else
filter = $"{{ _id : {id.AsInt64} }}"; // some kind of int
return await collection.UpdateOneAsync(filter, BsonJsonSerializer.ToBsonDocument(objA), updateOptions, cancellationToken);
}
public async static Task DeleteOneAsync(this IMongoCollection collection, string Json, CancellationToken cancellationToken = default)
{
return await collection.DeleteOneAsync(BsonDocument.Parse(Json), cancellationToken);
}
public async static Task DeleteOneByIdAsync(this IMongoCollection collection, object objA, CancellationToken cancellationToken = default)
{
var doc = BsonJsonSerializer.ToBsonDocument(objA);
var id = doc["_id"];
string filter;
if (id.IsGuid)
filter = $"{{ _id : UUID('{id.AsGuid}') }}";
else if (id.IsObjectId)
filter = $"{{ _id : ObjectId('{id.AsObjectId}') }}";
else if (id.IsString)
filter = $"{{ _id : '{id.AsString}' }}";
else
filter = $"{{ _id : {id.AsInt64} }}"; // some kind of int
return await collection.DeleteOneAsync(filter, cancellationToken);
}
public async static Task DeleteOneAsync(this IMongoCollection collection, object objA, CancellationToken cancellationToken = default)
{
return await collection.DeleteOneAsync(BsonJsonSerializer.ToBsonDocument(objA), cancellationToken);
}
public async static Task> AggregateAsync(this IMongoCollection collection, string JsonDocuments, AggregateOptions? options = null, CancellationToken cancellationToken = default)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
return await collection.AggregateAsync(bsonDocuments, options, cancellationToken);
}
public async static Task CountAsync(this IMongoCollection collection, CountOptions? options = null, CancellationToken cancellationToken = default)
{
return await collection.CountDocumentsAsync("{}", options, cancellationToken);
}
public async static Task CountDocumentsAsync(this IMongoCollection collection, CountOptions? options = null, CancellationToken cancellationToken = default)
{
return await collection.CountDocumentsAsync("{}", options, cancellationToken);
}
public async static Task> BulkWriteAsync(this IMongoCollection collection, string JsonDocuments, WriteConcern? writeConcern = null, BulkWriteOptions? options = null, CancellationToken cancellationToken = default)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
var requests = new List>();
foreach (var bsonDocument in bsonDocuments)
{
var first = bsonDocument.Elements.FirstOrDefault();
var doc = first.Value.AsBsonDocument;
switch (first.Name)
{
default:
break;
case "insertOne":
requests.Add(new InsertOneModel(doc.GetValue("document").AsBsonDocument));
break;
case "updateOne":
requests.Add(new UpdateOneModel(doc.GetValue("filter").AsBsonDocument, doc.GetValue("update").AsBsonDocument));
break;
case "deleteOne":
requests.Add(new DeleteOneModel(doc.GetValue("filter").AsBsonDocument));
break;
case "replaceOne":
requests.Add(new ReplaceOneModel(doc.GetValue("filter").AsBsonDocument, doc.GetValue("replacement").AsBsonDocument));
break;
case "updateMany":
requests.Add(new UpdateManyModel(doc.GetValue("filter").AsBsonDocument, doc.GetValue("update").AsBsonDocument));
break;
case "deleteMany":
requests.Add(new DeleteManyModel(doc.GetValue("filter").AsBsonDocument));
break;
}
}
if (writeConcern != null)
return await collection.WithWriteConcern(writeConcern).BulkWriteAsync(requests, options, cancellationToken);
else
return await collection.BulkWriteAsync(requests, options, cancellationToken);
}
public async static Task> WatchAsync(this IMongoCollection collection, string JsonDocuments, ChangeStreamOptions? options = null, CancellationToken cancellationToken = default)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
return await collection.WatchAsync(bsonDocuments, options, cancellationToken);
}
// General
// ==============================================================================================================
public static IMongoCollection GetCollection(this IMongoDatabase db, string CollectionName, MongoCollectionSettings? settings = null)
{
return db.GetCollection(CollectionName, settings);
}
public static string Pretty(this List list,BsonJsonSerializer.TypeSerializationEnum typeSerializationEnum)
{
return BsonJsonSerializer.ToJson(list, new JsonSerializerOptions() { WriteIndented = true }, typeSerializationEnum);
}
public static string Pretty(this List list, BsonJsonSerializer.TypeSerializationEnum typeSerializationEnum)
{
return list.Select(x => x.ToBsonDocument()).ToList().Pretty(typeSerializationEnum);
}
public static string Pretty(this IAsyncCursor cursor, BsonJsonSerializer.TypeSerializationEnum typeSerializationEnum)
{
return cursor.ToList().Pretty(typeSerializationEnum);
}
public static string Pretty(this IMongoCollection collection, BsonJsonSerializer.TypeSerializationEnum typeSerializationEnum)
{
return collection.Find("{}").ToList().Pretty(typeSerializationEnum);
}
// Extensions synchronous
// ==============================================================================================================
public static IFindFluent? Where(this IMongoCollection collection, Expression> filter)
{
return collection.Find(filter);
}
public static T? FirstOrDefault(this IMongoCollection collection, Expression> filter)
{
var results = collection.Find(filter);
return results.FirstOrDefault();
}
public static BsonDocument RunCommand(this IMongoDatabase db, string JsonDocument, ReadPreference? readPreference = null)
{
return db.RunCommand(BsonDocument.Parse(JsonDocument), readPreference);
}
public static BsonValue InsertOne(this IMongoCollection collection, object objA, InsertOneOptions? options = null, CancellationToken cancellationToken = default)
{
var doc = BsonJsonSerializer.ToBsonDocument(objA);
collection.InsertOne(doc, options, cancellationToken);
return doc["_id"];
}
public static List InsertMany(this IMongoCollection collection, string JsonDocuments, InsertManyOptions? options = null)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
collection.InsertMany(bsonDocuments, options);
return bsonDocuments.Select(x => x["_id"]).ToList();
}
public static IAsyncCursor Aggregate(this IMongoCollection collection, string JsonDocuments, AggregateOptions? options = null)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
return collection.Aggregate(bsonDocuments, options);
}
[Obsolete("Use CountDocuments or EstimatedDocumentCount instead.")]
public static long Count(this IMongoCollection collection, CountOptions? options = null)
{
return collection.Count("{}", options);
}
public static long CountDocuments(this IMongoCollection collection, CountOptions? options = null)
{
return collection.CountDocuments("{}", options);
}
public static BulkWriteResult BulkWrite(this IMongoCollection collection, string JsonDocuments, WriteConcern? writeConcern = null, BulkWriteOptions? options = null)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
var requests = new List>();
foreach (var bsonDocument in bsonDocuments)
{
var first = bsonDocument.Elements.FirstOrDefault();
var doc = first.Value.AsBsonDocument;
switch (first.Name)
{
default:
break;
case "insertOne":
requests.Add(new InsertOneModel(doc.GetValue("document").AsBsonDocument));
break;
case "updateOne":
requests.Add(new UpdateOneModel(doc.GetValue("filter").AsBsonDocument, doc.GetValue("update").AsBsonDocument));
break;
case "deleteOne":
requests.Add(new DeleteOneModel(doc.GetValue("filter").AsBsonDocument));
break;
case "replaceOne":
requests.Add(new ReplaceOneModel(doc.GetValue("filter").AsBsonDocument, doc.GetValue("replacement").AsBsonDocument));
break;
case "updateMany":
requests.Add(new UpdateManyModel(doc.GetValue("filter").AsBsonDocument, doc.GetValue("update").AsBsonDocument));
break;
case "deleteMany":
requests.Add(new DeleteManyModel(doc.GetValue("filter").AsBsonDocument));
break;
}
}
if (writeConcern != null)
return collection.WithWriteConcern(writeConcern).BulkWrite(requests, options);
else
return collection.BulkWrite(requests, options);
}
public static IChangeStreamCursor Watch(this IMongoCollection collection, string JsonDocuments, ChangeStreamOptions? options = null)
{
var bsonDocuments = BsonSerializer.Deserialize(JsonDocuments);
return collection.Watch(bsonDocuments, options);
}
// ------------------------------------
public async static Task FirsOrDefaultAsync(this IMongoCollection collection, Expression> filter)
{
var results = await collection.FindAsync(filter);
if (results == null)
return default;
else
return await results.FirstOrDefaultAsync();
}
}