// Copyright Epic Games, Inc. All Rights Reserved. using MongoDB.Driver; using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Threading.Tasks; namespace EpicGames.MongoDB { /// /// Extension methods for MongoDB /// public static class MongoExtensions { /// /// Filters the documents returned from a search /// /// The query to filter /// Index of the first document to return /// Number of documents to return /// New query public static IFindFluent Range(this IFindFluent query, int? index, int? count) { if (index != null) { query = query.Skip(index.Value); } if(count != null) { query = query.Limit(count.Value); } return query; } /// /// Filters the documents returned from a search /// /// The query to filter /// New query public static async Task> ToListAsync(this IAsyncCursorSource query) where TDocument : TResult { List results = new List(); using (IAsyncCursor cursor = await query.ToCursorAsync()) { while (await cursor.MoveNextAsync()) { foreach (TDocument document in cursor.Current) { results.Add(document); } } } return results; } /// /// Attempts to insert a document into a collection, handling the error case that a document with the given key already exists /// /// /// Collection to insert into /// The document to insert /// True if the document was inserted, false if it already exists public static async Task InsertOneIgnoreDuplicatesAsync(this IMongoCollection collection, TDocument newDocument) { try { await collection.InsertOneAsync(newDocument); return true; } catch (MongoWriteException ex) { if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) { return false; } else { throw; } } } /// /// Sets a field to a value, or unsets it if the value is null /// /// The document type /// Type of the field to set /// Update builder /// Expression for the field to set /// New value to set /// Update defintiion public static UpdateDefinition SetOrUnsetNull(this UpdateDefinitionBuilder updateBuilder, Expression> field, TField? value) where TField : struct { if (value.HasValue) { return updateBuilder.Set(field, value.Value); } else { return updateBuilder.Unset(new ExpressionFieldDefinition(field)); } } /// /// Sets a field to a value, or unsets it if the value is null /// /// The document type /// Type of the field to set /// Update builder /// Expression for the field to set /// New value to set /// Update defintiion public static UpdateDefinition SetOrUnsetNullRef(this UpdateDefinitionBuilder updateBuilder, Expression> field, TField? value) where TField : class { if (value != null) { return updateBuilder.Set(field, value); } else { return updateBuilder.Unset(new ExpressionFieldDefinition(field)); } } /// /// Creates a filter definition from a linq expression. This is not generally explicitly castable, so expose it as a FilterDefinitionBuilder method. /// /// The document type /// The filter builder /// Expression to parse /// New filter definition [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter")] public static FilterDefinition Expr(this FilterDefinitionBuilder filter, Expression> expression) { return expression; } } }