Skip to content

Instantly share code, notes, and snippets.

@Davoodeh
Last active October 11, 2021 13:10
Show Gist options
  • Save Davoodeh/2cdb5ea7480a4c69e2cf3be086aa3255 to your computer and use it in GitHub Desktop.
Save Davoodeh/2cdb5ea7480a4c69e2cf3be086aa3255 to your computer and use it in GitHub Desktop.
Hacky Database Relation Module/Manager/Model (HDBRM)
using System;
using System.Collections.Generic;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Driver;
// modified HDBRM, upstream: https://gist.github.com/Davoodeh/2cdb5ea7480a4c69e2cf3be086aa3255
namespace HDBRM
{
public class DB
{
private readonly string _DBName;
private readonly string _DBURL;
private readonly MongoClient _client;
private readonly IMongoDatabase _base;
public readonly CollectionsDictionary Collections;
public readonly CommonFiltersDictionary CommonFilters = new CommonFiltersDictionary() { };
/// <summary>
/// Open and maintain a connection to the MongoDB database and
/// prepares the necessary Collections as a dictionary.
/// </summary>
///
/// <param name="DBName">The name of the database</param>
/// <param name="DBURL">The URL/Location of the database (default
/// localhost)</param>
/// <param name="collectionNames">An array containing the name of
/// Collections to be retrieve on construction.</param>
public DB(string DBName, string DBURL = "mongodb://127.0.0.1:27017", string[] collectionsNames = null)
{
_DBName = DBName;
_DBURL = DBURL;
// TODO add more check for whether DB exists or _client could actually connect or not
_client = new MongoClient(_DBURL);
_base = _client.GetDatabase(_DBName);
Collections = new CollectionsDictionary(_base) { };
if (collectionsNames != null)
Collections.Add(collectionsNames);
}
/// <summary>
/// Makes a an <c>Filter.Eq</c> with all the given pairs as if they are
/// <c>Eq(firstPair.Key, firstPair.Value) & Eq(secondPair.Key,
/// secondPair.Value) & ...</c>.
/// </summary>
///
/// <param name="pairs">A dictionary containing the name of a field as
/// its Key and the expected value as its Value for feeding to Eq
/// function</param>
///
/// <returns>The generated filter</returns>
public static FilterDefinition<BsonDocument> EqFilter(Dictionary<string, object> pairs)
{
FilterDefinition<BsonDocument>[] final = new FilterDefinition<BsonDocument>[pairs.Count];
int c = 0;
foreach (KeyValuePair<string, object> i in pairs)
final[c++] = Builders<BsonDocument>.Filter.Eq(i.Key, i.Value);
return AddFilters(final);
}
/// <summary>
/// Ands all the elements in the given filter array.
/// </summary>
public static FilterDefinition<BsonDocument> AddFilters(FilterDefinition<BsonDocument>[] filters)
{
FilterDefinition<BsonDocument> final = filters[0];
for (int i = 0; i < filters.Length; i++)
final &= filters[i];
return final;
}
public sealed class CollectionsDictionary : Dictionary<string, IMongoCollection<BsonDocument>>
{
private readonly IMongoDatabase _base;
public CollectionsDictionary(IMongoDatabase Base) => _base = Base;
/// <summary>
/// Introduce a new collection to the Collection keys.
/// </summary>
///
/// <param name="collectionName">Is the exact string name of the
/// collection to be fetched from the database.</param>
public void Add(string collectionName) =>
base.Add(collectionName, _base.GetCollection<BsonDocument>(collectionName));
public void Add(string[] collectionsNames)
{
foreach (string i in collectionsNames)
Add(i);
}
/// <summary>
/// An insert that does not throw on error. This is defined just
/// for compatibility reasons, do NOT use this.
/// </summary>
///
/// <returns>True if no exception is thrown.</returns>
[Obsolete("Use the standard InsertOne method of Mongo Collections with properly defined catches")]
public bool SuppressedInsert(string collectionName, BsonDocument data)
{
try
{
base[collectionName].InsertOne(data);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// A simple method equal to the common "Filter, Find, FindOrDefault" operation.
/// </summary>
///
/// <param name="collectionName">Is the name of the previously added collection.</param>
/// <param name="filter">Is a dictionary object which turns to a filter using <c>EqFilter</c></param>
///
/// <returns>The results of the query</returns>
///
/// <seealso cref="EqFilter" />
public BsonDocument FindFirstOrDefault(string collectionName, Dictionary<string, object> filter) =>
base[collectionName].Find(DB.EqFilter(filter)).FirstOrDefault();
}
public sealed class CommonFiltersDictionary : Dictionary<string, FilterDefinition<BsonDocument>>
{
/// <summary>
/// Make adding one non-complex filter to the common filters simpler.
/// </summary>
///
/// <param name="key">Will determine the place of the generated
/// filter in the dictionary.</param>
/// <param name="field">Will be passed as the first parameter to
/// Eq.</param>
/// <param name="value">Will be passed as the second parameter to
/// Eq.</param>
public void AddEqFilter(string key, string field, object value) =>
base.Add(key, DB.EqFilter(new Dictionary<string, object> { { field, value } }));
/// <summary>
/// Create a new compound filter by anding two previously added filters
/// under a distinct new key.
/// Newly generated compound filter will live under <c>names.join(&)</c>.
/// </summary>
///
/// <param name="namesString">Is the name of previously added filters that
/// need to be in the mix.</param>
public void AddCompoundFilter(string namesString)
{
string[] names = namesString.Split('&');
FilterDefinition<BsonDocument>[] filters = new FilterDefinition<BsonDocument>[names.Length];
for (int i = 0; i < names.Length; i++)
filters[i] = base[names[i]];
base.Add(string.Join("&", names), DB.AddFilters(filters));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment