sql >> Database >  >> NoSQL >> MongoDB

Hoe een klasse-item te versieren als een index en hetzelfde te krijgen als het gebruik van assuranceIndex?

Ik vind dit een leuk idee, maar je moet dit zelf doen, er is geen ingebouwde ondersteuning voor. Als je een toegangslaag hebt, kun je dat daar doen. Je hebt een attribuutklasse nodig, zoiets als dit;

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

U kunt dan als volgt attributen toepassen op klas- of lidniveau. Ik ontdekte dat toevoegen op ledenniveau minder snel uit de pas liep met het schema dan toevoegen op klasniveau. Je moet er natuurlijk voor zorgen dat je de daadwerkelijke elementnaam krijgt in plaats van de C#-lidnaam;

[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
}

en dan heb je in je DB-toegangsimplementatie (of repository) zoiets als dit nodig;

    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()

ZorgenIndexes ziet er dan zo uit;

    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()

Houd er rekening mee dat u dit na elke update plaatst, want als u het ergens vergeet, worden uw indexen mogelijk niet gemaakt. Het is daarom belangrijk om ervoor te zorgen dat u de aanroep optimaliseert, zodat deze snel terugkeert als er geen indexering hoeft te worden uitgevoerd voordat u al die reflectiecode doorloopt. In het ideale geval zou u dit slechts één keer doen, of op zijn minst één keer per applicatie-opstart. Dus een manier zou zijn om een ​​statische vlag te gebruiken om bij te houden of je dit al hebt gedaan, en je zou daar extra vergrendelingsbeveiliging voor nodig hebben, maar te simplistisch ziet het er ongeveer zo uit;

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

Dus dat is de methode die je nodig hebt in elke DB-update die je maakt, die, als je geluk hebt, ook door de JIT-optimizer wordt opgenomen.



  1. Is er een manier om paginering te implementeren in de lente webflux en reactieve lentegegevens?

  2. C# MongoDB - Hoe kan ik een item toevoegen aan en verwijderen uit meerdere geneste array-elementen?

  3. Krijg het aantal logniveaus voor elke naam

  4. Android:mijn applicatie werkt niet omdat ik een onbekende hostuitzondering moet afhandelen. wanneer ik het doe crasht