MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Как да декорирате елемент от класа, за да бъде индекс и да получите същото като при използване на secureIndex?

Мисля, че това е хубава идея, но трябва да го направите сами, няма вградена поддръжка за това. Ако имате слой за достъп, можете да го направите там. Ще ви трябва клас атрибут, нещо подобно;

public enum IndexConstraints
{
    Normal     = 0x00000001, // Ascending, non-indexed
    Descending = 0x00000010,
    Unique     = 0x00000100,
    Sparse     = 0x00001000, // allows nulls in the indexed fields
}

// Applied to a member
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class EnsureIndexAttribute : EnsureIndexes
{
    public EnsureIndex(IndexConstraints ic = IndexConstraints.Normal) : base(ic) { }
}

// Applied to a class
[AttributeUsage(AttributeTargets.Class)]
public class EnsureIndexesAttribute : Attribute
{
    public bool Descending { get; private set; }
    public bool Unique { get; private set; }
    public bool Sparse { get; private set; }
    public string[] Keys { get; private set; }

    public EnsureIndexes(params string[] keys) : this(IndexConstraints.Normal, keys) {}
    public EnsureIndexes(IndexConstraints ic, params string[] keys)
    {
        this.Descending = ((ic & IndexConstraints.Descending) != 0);
        this.Unique = ((ic & IndexConstraints.Unique) != 0); ;
        this.Sparse = ((ic & IndexConstraints.Sparse) != 0); ;
        this.Keys = keys;
    }

}//class EnsureIndexes

След това можете да приложите атрибути на ниво клас или член, както следва. Открих, че добавянето на ниво член е по-малко вероятно да излезе от синхрон със схемата в сравнение с добавянето на ниво клас. Разбира се, трябва да се уверите, че получавате действителното име на елемента, а не името на члена на C#;

[CollectionName("People")]
//[EnsureIndexes("k")]// doing it here would allow for multi-key configs
public class Person 
{
    [BsonElement("k")] // name mapping in the DB schema
    [BsonIgnoreIfNull]
    [EnsureIndex(IndexConstraints.Unique|IndexConstraints.Sparse)] // name is implicit here
    public string userId{ get; protected set; }

// other properties go here
}

и след това във вашата реализация за достъп до DB (или хранилище), имате нужда от нещо подобно;

    private void AssureIndexesNotInlinable()
    {
                // We can only index a collection if there's at least one element, otherwise it does nothing
                if (this.collection.Count() > 0)
                {

                    // Check for EnsureIndex Attribute
                    var theClass = typeof(T);

                    // Walk the members of the class to see if there are any directly attached index directives
                    foreach (var m in theClass.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
                    {
                        List<string> elementNameOverride = new List<string>(1);
                        EnsureIndexes indexAttr = null;

                        // For each members attribs
                        foreach (Attribute attr in m.GetCustomAttributes())
                        {
                            if (attr.GetType() == typeof(EnsureIndex))
                                indexAttr = (EnsureIndex)attr;

                            if (attr.GetType() == typeof(RepoElementAttribute))
                                elementNameOverride.Add(((RepoElementAttribute)attr).ElementName);

                            if ((indexAttr != null) && (elementNameOverride.Count != 0))
                                break;
                        }

                        // Index
                        if (indexAttr != null)
                        {
                            if (elementNameOverride.Count() > 0)
                                EnsureIndexesAsDeclared(indexAttr, elementNameOverride);
                            else
                                EnsureIndexesAsDeclared(indexAttr);
                        }
                    }

                    // Walk the atributes on the class itself. WARNING: We don't validate the member names here, we just create the indexes
                    // so if you create a unique index and don't have a field to match you'll get an exception as you try to add the second
                    // item with a null value on that key
                    foreach (Attribute attr in theClass.GetCustomAttributes(true))
                    {
                        if (attr.GetType() == typeof(EnsureIndexes))
                            EnsureIndexesAsDeclared((EnsureIndexes)attr);

                    }//foreach

                }//if this.collection.count

    }//AssureIndexesNotInlinable()

Тогава EnsureIndexes изглежда така;

    private void EnsureIndexesAsDeclared(EnsureIndexes attr, List<string> indexFields = null)
    {
        var eia = attr as EnsureIndexes;

        if (indexFields == null)
            indexFields = eia.Keys.ToList();

        // use driver specific methods to actually create this index on the collection
        var db = GetRepositoryManager(); // if you have a repository or some other method of your own 
        db.EnsureIndexes(indexFields, attr.Descending, attr.Unique, attr.Sparse);

    }//EnsureIndexes()

Обърнете внимание, че ще поставяте това след всяка актуализация, защото ако забравите някъде, вашите индекси може да не бъдат създадени. Ето защо е важно да се уверите, че оптимизирате повикването, така че да се върне бързо, ако няма индексиране, което да се направи, преди да преминете през целия този код за отразяване. В идеалния случай бихте направили това само веднъж или най-малкото веднъж на стартиране на приложение. Така че един от начините би бил да използвате статичен флаг, за да проследите дали вече сте го направили, и ще ви е необходима допълнителна защита за заключване около това, но прекалено опростено, изглежда по следния начин;

    void AssureIndexes()
    {
        if (_requiresIndexing)
            AssureIndexesInit();
    }

Така че това е методът, който ще искате във всяка актуализация на БД, която правите, който, ако имате късмет, ще бъде включен и от JIT оптимизатора.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Изложете само определени полета, когато преглеждате конкретен елемент с Spring Data?

  2. Групово upsert с драйвер MongoDB Java 3.0

  3. $push с позиционен ($) в upsert е неуспешен

  4. Как да преместите елемент в MongoDB масив?

  5. mongoDB агрегиране:сума въз основа на имена на масиви