// Copyright Epic Games, Inc. All Rights Reserved. using System.Diagnostics; using System.Text; using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; namespace HordeServer.Server { /// /// Constrained set of parameters for building a mongo index /// [DebuggerDisplay("{Name}")] public class MongoIndex : IEquatable { /// /// Name of the index /// [BsonElement("name"), BsonRequired] public string Name { get; private set; } /// /// Keys for the index /// [BsonElement("key"), BsonRequired] public BsonDocument KeysDocument { get; private set; } /// /// The index should be unique /// [BsonElement("unique")] public bool Unique { get; private set; } /// /// Whether to create a sparse index /// [BsonElement("sparse")] public bool Sparse { get; private set; } /// /// Constructor /// [BsonConstructor] private MongoIndex() { Name = String.Empty; KeysDocument = new BsonDocument(); } /// /// Constructor /// /// Name of the index /// Keys for the index /// Whether the index should be unique /// Whether to create a sparse index public MongoIndex(string? name, BsonDocument keysDocument, bool unique, bool sparse) { Name = name ?? GetDefaultName(keysDocument); KeysDocument = keysDocument; Unique = unique; Sparse = sparse; } /// /// Constructor /// /// Callback to configure keys for this document /// Whether the index should be unique /// Whether to create a sparse index public static MongoIndex Create(Func, IndexKeysDefinition> keysFunc, bool unique = false, bool sparse = false) { return new MongoIndex(null, keysFunc(Builders.IndexKeys), unique, sparse); } /// /// Constructor /// /// Name of the index /// Callback to configure keys for this document /// Whether the index should be unique /// Whether to create a sparse index public static MongoIndex Create(string name, Func, IndexKeysDefinition> keysFunc, bool unique = false, bool sparse = false) { return new MongoIndex(name, keysFunc(Builders.IndexKeys), unique, sparse); } /// public override bool Equals(object? obj) => obj is MongoIndex other && Equals(other); /// public override int GetHashCode() => Name.GetHashCode(StringComparison.Ordinal); /// public bool Equals(MongoIndex? other) => other != null && Name.Equals(other.Name, StringComparison.Ordinal) && KeysDocument.Equals(other.KeysDocument) && Sparse == other.Sparse && Unique == other.Unique; /// /// Gets the default name for an index based on its keys /// /// Keys for the index /// Name of the index protected static string GetDefaultName(BsonDocument keys) { StringBuilder name = new StringBuilder(); foreach (BsonElement element in keys.Elements) { if (name.Length > 0) { name.Append('_'); } name.Append(element.Name); name.Append('_'); name.Append(element.Value.ToString()); } return name.ToString(); } } /// /// Strongly typed index document /// /// public class MongoIndex : MongoIndex { /// /// Keys for the index /// [BsonIgnore] public IndexKeysDefinition Keys { get; } /// /// Constructor /// /// Name of the index /// Keys for the index /// Whether the index should be unique /// Whether to create a sparse index public MongoIndex(string? name, IndexKeysDefinition keys, bool unique, bool sparse) : base(name, keys.Render(BsonSerializer.LookupSerializer(), BsonSerializer.SerializerRegistry), unique, sparse) { Keys = keys; } } /// /// Extension methods for /// public static class MongoIndexExtensions { /// /// Adds a new index to the collection /// public static void Add(this List> list, Func, IndexKeysDefinition> keyFunc, bool unique = false, bool sparse = false) { list.Add(MongoIndex.Create(keyFunc, unique, sparse)); } /// /// Adds a new index to the collection /// public static void Add(this List> list, string name, Func, IndexKeysDefinition> keyFunc, bool unique = false, bool sparse = false) { list.Add(MongoIndex.Create(name, keyFunc, unique, sparse)); } } }