Как создать индекс MongoDB MultiKey на атрибуте элементов в array.NET драйвер

у меня есть коллекция MongoDB "foos", содержащая элементы, каждый из которых имеет массив"баров". То есть "foo" имеет следующую схему:

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

мне нужно создать индекс на имя и бар.ключ с помощью драйвера MongoDB C# .NET Mongo.

я предположил, что могу использовать функцию Linq Select для этого следующим образом:

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

однако это приводит к InvalidOperationException:

система.InvalidOperationException: 'невозможно определите информацию о сериализации для x => x.Бары.Выберите (y => y.Id).'

документация Монго на MultiKey индексы показывает, как создать такой индекс, используя простую точечную нотацию, т. е.

db.foos.createIndex( { "name": 1, "bars.key": 1 } )
документация по драйверу MongoDB похоже, что использование функции Linq, как я делаю, правильно.

как создать многоключевой индекс в моей коллекции с помощью драйвера MongoDB .NET, предпочтительно использовать функцию Linq?

3 ответов


это пример того, как это сделать с 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#, что означает"$" (доказательство). Таким образом, этот код попытается создать индекс:

{ "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 }

поэтому в основном я не думаю, что это возможно прямо сейчас построить индекс вы хотите с чистым Linq без изменения драйверов mongo C#.

поэтому я думаю, что ваш единственный вариант сделать это, все еще C#, но без Linq

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

Вы можете создать индекс строки и использовать nameof() в C# 6:

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

Это запрошенная функция для драйвера C#, хотя он не видел никакого прогресса. Тем не менее, кто-то представил грубое и готовое решение там на потоке JIRA, так что, возможно, это сделает работу за вас.