web-dev-qa-db-ja.com

配列.NETドライバーの項目の属性にMongoDB MultiKeyインデックスを作成する方法

私はそれぞれが「バー」の配列を持つアイテムを含むMongoDBコレクション「foos」を持っています。つまり、「foo」には次のスキーマがあります。

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

MongoDB C#.NET Mongoドライバーを使用して、nameとbar.keyにインデックスを作成する必要があります。

次のように、Linq Select関数を使用してこれを実行できると思いました。

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

ただし、これによりInvalidOperationExceptionが発生します。

System.InvalidOperationException: 'x => x.Bars.Select(y => y.Id)のシリアル化情報を特定できません。'

MultiKeyインデックスに関するMongoのドキュメント は、単純なドット表記を使用してそのようなインデックスを作成する方法を示しています。

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

ただし、 MongoDBドライバーのドキュメント は、私がしているようにLinq関数を使用することが正しいことを示唆しているようです。

MongoDB .NETドライバーを使用して、できればLinq関数を使用して、コレクションにマルチキーインデックスを作成するにはどうすればよいですか

14
Ivan

これは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); 

[〜#〜]更新[〜#〜]

配列内のインデックスに関して、私が見つけることができた最も近いものは、インデックスキーを構築するときにインデックスとして「-1」を使用することです。私がgithubソースコードから理解しているように、クエリを構築する場合には有効なオプションです。

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」は、サイドのmongodb C#ドライバーにハードコードされた定数で、「$」を意味します( proof )。したがって、このコードはインデックスを作成しようとします:

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

これは、データベースからの情報のクエリには適していますが、インデックスで使用することはできません(「インデックスキーに不正なフィールド名が含まれています:フィールド名が「$」で始まる」という例外がスローされます)。だから私はそれを動作させるためにmongodbドライバで変更する必要があると思います。 「-2」のようなものは空の演算子を意味します。その場合は、

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

これは次のようなインデックスを生成します:

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

基本的に、mongo C#ドライバーを変更せずに、純粋なLinqで必要なインデックスを構築することは現時点では不可能だと思います

だから私はあなたの唯一のオプションがこのようにやっていると思います、まだC#で​​すがLinqなし

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

これは C#ドライバーに要求された機能 のようですが、最近は進展が見られません。とは言っても、誰かがJIRAスレッドで大まかな準備のできたソリューションをそこに提出したので、おそらくそれがあなたのために働くでしょう。

7
Noldorin

文字列インデックスを作成し、C#6でnameof()を使用できます。

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

_"MongoDB.Driver" Version="2.8.0"_の構文が変更され、一部のメソッドが非推奨になりました。以下は同じことを実現する方法です。 CreateOneAsync(new CreateIndexModel<FooDocument>(indexDefinition));部分に注意してください

_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(new CreateIndexModel<FooDocument>(indexDefinition)); 
_
1
nandithakw