I have a MongoDB collection "foos" containing items which each have an array of "bars". That is, "foo" has the following schema:
{
"id": UUID
"name": string
...
"bars": [
"id": UUID
"key": string
...
]
}
I need to create an index on name and bar.key using the MongoDB C# .NET Mongo driver.
I presumed I could use a Linq Select function to do this as follows:
Indexes.Add(Context.Collection<FooDocument>().Indexes.CreateOne(
Builders<FooDocument>.IndexKeys
.Descending(x => x.Bars.Select(y => y.Key))));
However this results in an InvalidOperationException:
System.InvalidOperationException: 'Unable to determine the serialization information for x => x.Bars.Select(y => y.Id).'
The Mongo documentation on MultiKey indexes shows how to create such an index using simple dot notation, i.e.
db.foos.createIndex( { "name": 1, "bars.key": 1 } )
However the MongoDB driver documentation seems to suggest that using a Linq function as I'm doing is correct.
How can I create a multikey index on my collection using the MongoDB .NET Driver, preferably using a Linq function?
This is an example how to do it with 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
Regarding index within the array, closest what i was able to find is to use "-1" as index whene you building your index key. As i understand from github source code is is a valid option in case of building queries.
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" is a hardcoded constant in side mongodb C# drivers which means "$" (proof). So this code would try to create index:
{ "Key1": 1, "Key2.$.Key": 1 }
which is fine for querying info from database, but not allowed (will throw an exception "Index key contains an illegal field name: field name starts with '$'") to use in indexes. So i assume it should be changed in mongodb drivers to make it work. Something like "-2" means empty operator. In that case we could use
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);
which would generate index like:
{ "Key1": 1, "Key2.Key": 1 }
So basically i don't think it is possible right now to build index you want with pure Linq without changing mongo C# drivers.
So i think your only option do like this, still C# but without Linq
await collection.Indexes.CreateOneAsync(new BsonDocument {{"name", 1}, {"bars.key", 1}});
This appears to be a requested feature for the C# driver, although it hasn't seen any progress lately. That said, someone did submit a rough-and-ready solution there on the JIRA thread, so perhaps that will do the job for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With