web-dev-qa-db-fra.com

Comment créer un index MongoDB MultiKey sur l'attribut d'éléments d'un tableau .NET Driver

J'ai une collection MongoDB "foos" contenant des éléments qui ont chacun un tableau de "barres". C'est-à-dire que "foo" a le schéma suivant:

{
    "id": UUID
    "name": string
    ...
    "bars": [
        "id": UUID
        "key": string
        ...
    ]
}

Je dois créer un index sur name et bar.key à l'aide du pilote MongoDB C # .NET Mongo.

J'ai supposé que je pourrais utiliser une fonction Linq Select pour le faire comme suit:

Indexes.Add(Context.Collection<FooDocument>().Indexes.CreateOne(
    Builders<FooDocument>.IndexKeys
        .Descending(x => x.Bars.Select(y => y.Key))));

Toutefois, cela entraîne une exception InvalidOperationException:

System.InvalidOperationException: 'Impossible de déterminer les informations de sérialisation pour x => x.Bars.Select (y => y.Id).'

La documentation Mongo sur les index MultiKey montre comment créer un tel index en utilisant la notation simple par points, c.-à-d.

db.foos.createIndex( { "name": 1, "bars.key": 1 } )

Cependant, la documentation du pilote MongoDB } semble suggérer que l’utilisation d’une fonction Linq comme je le fais est correcte. 

Comment créer un index multikey sur ma collection à l'aide du pilote MongoDB .NET, de préférence à l'aide d'une fonction Linq?

10
Ivan

Ceci est un exemple comment faire avec C #

var indexDefinition = Builders<FooDocument>.IndexKeys.Combine(
    Builders<FooDocument>.IndexKeys.Ascending(f => f.Key1),
    Builders<FooDocument>.IndexKeys.Ascending(f => f.Key2));

await collection.Indexes.CreateOneAsync(indexDefinition); 

UPDATE

En ce qui concerne l'index dans le tableau, ce que j'ai pu trouver est d'utiliser "-1" comme index lorsque vous construisez votre clé d'index. Comme je comprends de github, le code source est une option valide dans le cas de requêtes de construction.

var indexDefinition = Builders<FooDocument>.IndexKeys.Combine(
    Builders<FooDocument>.IndexKeys.Ascending(f => f.Key1),
    Builders<FooDocument>.IndexKeys.Ascending(f => f.Key2[-1].Key));

await collection.Indexes.CreateOneAsync(indexDefinition); 

"-1" est une constante codée en dur dans les pilotes mongodb C # qui signifie "$" ( proof ). Donc, ce code essaierait de créer un index: 

{ "Key1": 1, "Key2.$.Key": 1 }

ce qui est bien pour interroger des informations depuis la base de données, mais pas autorisé (une exception "La clé d'index contient un nom de champ non autorisé: le nom de champ commence par '$'") à utiliser dans les index. Je suppose donc que cela devrait être changé dans les pilotes mongodb pour que cela fonctionne. Quelque chose comme "-2" signifie un opérateur vide. Dans ce cas, nous pourrions utiliser 

var indexDefinition = Builders<FooDocument>.IndexKeys.Combine(
    Builders<FooDocument>.IndexKeys.Ascending(f => f.Key1),
    Builders<FooDocument>.IndexKeys.Ascending(f => f.Key2[-2].Key));

await collection.Indexes.CreateOneAsync(indexDefinition); 

qui générerait un index comme:

{ "Key1": 1, "Key2.Key": 1 }

Donc en gros, je ne pense pas qu'il soit possible pour le moment de construire l'index que vous voulez avec Linq pur sans changer les drivers mongo C #.

Je pense donc que votre seule option est la même, toujours en C # mais sans Linq

await collection.Indexes.CreateOneAsync(new BsonDocument {{"name", 1}, {"bars.key", 1}});
8
Artyom

Vous pouvez créer un index de chaîne et utiliser nameof() en C # 6:

Indexes.Add(Context.Collection<FooDocument>().Indexes.CreateOne($"{nameof(FooDocument.Bars)}.{nameof(Bars.Key)}"));
4
Ollie P

Cela semble être une fonctionnalité demandée pour le pilote C # }, bien qu'il n'ait pas vu de progrès ces derniers temps. Cela dit, quelqu'un a soumis une solution simple sur le thread JIRA, alors peut-être que cela fera le travail pour vous.

3
Noldorin