如何在数组 .NET 驱动程序中的项目属性上创建 MongoDB MultiKey 索引
How to create MongoDB MultiKey index on attribute of items in an array .NET Driver
我有一个 Mongo 数据库集合 "foos",其中包含每个项目都有一个 "bars" 数组。也就是说,"foo" 具有以下架构:
{
"id": UUID
"name": string
...
"bars": [
"id": UUID
"key": string
...
]
}
我需要使用 MongoDB C# .NET Mongo 驱动程序在名称和 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: 'Unable to determine the serialization information for x => x.Bars.Select(y => y.Id).'
The Mongo documentation on MultiKey indexes 展示了如何使用简单的点符号创建这样的索引,即
db.foos.createIndex( { "name": 1, "bars.key": 1 } )
但是 the MongoDB driver documentation 似乎表明像我一样使用 Linq 函数是正确的。
如何使用 MongoDB .NET 驱动程序在我的集合上创建多键索引,最好使用 Linq 函数?
这是一个如何使用 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 }
这适用于从数据库查询信息,但不允许(将抛出异常 "Index key contains an illegal field name: field name starts with '$'")用于索引。所以我认为应该在 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}});
这似乎是 requested feature for the C# driver,虽然最近没有看到任何进展。也就是说,有人确实在 JIRA 线程上提交了一个粗略的解决方案,所以也许这会为你完成这项工作。
您可以创建字符串索引并在 C# 6 中使用 nameof()
:
Indexes.Add(Context.Collection<FooDocument>().Indexes.CreateOne($"{nameof(FooDocument.Bars)}.{nameof(Bars.Key)}"));
从 "MongoDB.Driver" Version="2.8.0"
开始,语法已经更改,一些方法已更改 deprecated.Following 是实现相同的方法。
请注意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));
根据之前的评论,C# driver still doesn't support 一种执行多键索引的强类型方式。
此外,使用 [-1]
之类的东西似乎有点老套,并不是您真正想要的,因为它将用 $
代替。
因此我建议这样做(从 MongoDB.Driver 2.8.0
开始):
var indexDefinition = Builders<FooDocument>.IndexKeys.Combine(
Builders<FooDocument>.IndexKeys.Ascending(f => f.Key1),
Builders<FooDocument>.IndexKeys.Ascending($"{nameof(FooDocument.Key2)}.{nameof(BarType.Key)}"));
await collection.Indexes.CreateOneAsync(new CreateIndexModel<FooDocument>(indexDefinition), cancellationToken: token);
我有一个 Mongo 数据库集合 "foos",其中包含每个项目都有一个 "bars" 数组。也就是说,"foo" 具有以下架构:
{
"id": UUID
"name": string
...
"bars": [
"id": UUID
"key": string
...
]
}
我需要使用 MongoDB C# .NET Mongo 驱动程序在名称和 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: 'Unable to determine the serialization information for x => x.Bars.Select(y => y.Id).'
The Mongo documentation on MultiKey indexes 展示了如何使用简单的点符号创建这样的索引,即
db.foos.createIndex( { "name": 1, "bars.key": 1 } )
但是 the MongoDB driver documentation 似乎表明像我一样使用 Linq 函数是正确的。
如何使用 MongoDB .NET 驱动程序在我的集合上创建多键索引,最好使用 Linq 函数?
这是一个如何使用 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 }
这适用于从数据库查询信息,但不允许(将抛出异常 "Index key contains an illegal field name: field name starts with '$'")用于索引。所以我认为应该在 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}});
这似乎是 requested feature for the C# driver,虽然最近没有看到任何进展。也就是说,有人确实在 JIRA 线程上提交了一个粗略的解决方案,所以也许这会为你完成这项工作。
您可以创建字符串索引并在 C# 6 中使用 nameof()
:
Indexes.Add(Context.Collection<FooDocument>().Indexes.CreateOne($"{nameof(FooDocument.Bars)}.{nameof(Bars.Key)}"));
从 "MongoDB.Driver" Version="2.8.0"
开始,语法已经更改,一些方法已更改 deprecated.Following 是实现相同的方法。
请注意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));
根据之前的评论,C# driver still doesn't support 一种执行多键索引的强类型方式。
此外,使用 [-1]
之类的东西似乎有点老套,并不是您真正想要的,因为它将用 $
代替。
因此我建议这样做(从 MongoDB.Driver 2.8.0
开始):
var indexDefinition = Builders<FooDocument>.IndexKeys.Combine(
Builders<FooDocument>.IndexKeys.Ascending(f => f.Key1),
Builders<FooDocument>.IndexKeys.Ascending($"{nameof(FooDocument.Key2)}.{nameof(BarType.Key)}"));
await collection.Indexes.CreateOneAsync(new CreateIndexModel<FooDocument>(indexDefinition), cancellationToken: token);