sql >> Database teknologi >  >> NoSQL >> MongoDB

Hvordan dekorerer man et klasseemne til at være et indeks og får det samme som at bruge sureIndex?

Jeg synes, det er en god idé, men du skal gøre dette selv, der er ingen indbygget understøttelse for det. Hvis du har et adgangslag, kan du gøre det derinde. Du skal bruge en attributklasse, sådan noget her;

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

Du kan derefter anvende attributter på enten klasse- eller medlemsniveau som følger. Jeg fandt ud af, at tilføjelse på medlemsniveau var mindre tilbøjelig til at komme ud af synkronisering med skemaet sammenlignet med tilføjelse på klasseniveau. Du skal selvfølgelig sørge for, at du får det faktiske elementnavn i modsætning til C#-medlemsnavnet;

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

og så i din DB-adgangsimplementering (eller repository), har du brug for noget som dette;

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

EnsureIndex ser så således ud;

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

Bemærk, at du placerer dette efter hver opdatering, fordi hvis du glemmer et sted, bliver dine indekser muligvis ikke oprettet. Det er derfor vigtigt at sikre, at du optimerer opkaldet, så det vender hurtigt tilbage, hvis der ikke er nogen indeksering, før du gennemgår al den refleksionskode. Ideelt set ville du gøre dette kun én gang eller i det mindste én gang pr. applikationsstart. Så en måde ville være at bruge et statisk flag til at spore, om du allerede har gjort det, og du har brug for yderligere låsebeskyttelse omkring det, men alt for forsimplet ser det sådan ud;

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

det er den metode, du vil have i hver eneste DB-opdatering, du laver, som, hvis du er heldig, også vil blive indsat af JIT-optimeringsværktøjet.



  1. Sådan finder du tilfældige poster i mongodb

  2. Database at vælge til spil

  3. Container administreret MongoDB Connection i Liberty + Spring Data

  4. MongoDB-projektets opdaterede post i et indlejret array i findAndModify-forespørgslen