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