66

I've programmatically created a new document collection using the MongoDB C# driver.

At this point I want to create and build indexes programmatically. How can I do that?

1

6 Answers 6

85

Starting from v2.0 of the driver there's a new async-only API. The old API should no longer be used as it's a blocking facade over the new API and is deprecated.

The currently recommended way to create an index is by calling and awaiting CreateOneAsync with an IndexKeysDefinition you get by using Builders.IndexKeys:

static async Task CreateIndexAsync()
{
    var client = new MongoClient();
    var database = client.GetDatabase("HamsterSchool");
    var collection = database.GetCollection<Hamster>("Hamsters");
    var indexKeysDefinition = Builders<Hamster>.IndexKeys.Ascending(hamster => hamster.Name);
    await collection.Indexes.CreateOneAsync(new CreateIndexModel<Hamster>(indexKeysDefinition));
}
Sign up to request clarification or add additional context in comments.

4 Comments

Quick question for the peanut gallery I am a big fan of the strongly typed lambdas in C# over magic strings elsewhere but the question becomes assume the Hamster object had an array of addresses (billing, physical, mailing, etc) and I also wanted to index by zip code. Unfortunately once you hit Builders<Hamster>.IndexKeys.Ascending(_ => _.Addresses.First().ZipCode) the index creates as if zip code was on the root class hamster. The documentation on docs.mongodb.com is sparse at best.
So you should create index only once at application startup?
@DavideQuaglio That's what I usually do. It's enough to only do it just once, but this guarantees idempotency.
46

you should use CreateIndex as EnsureIndex is marked obsolete for future compatibility with the next versions of MongoDB:

var client = new MongoClient("mongodb://localhost");
var db = client.GetServer().GetDatabase("db");
var collection = db.GetCollection<Hamster>("Hamsters");

collection.CreateIndex(IndexKeys<Hamster>.Ascending(_ => _.Name));

7 Comments

@PhilBarresi Do you mean drop the existing one and build a new one? Or simply build another index? Both do not happen.
Apparently I was wrong; it sends the command to build an index, but if the index is already built it will result in a no-op; my misunderstanding came from an error with a foreground index creation causing other createindex calls to become blocked, leading me to believe that they were rebuilding the index. Apologies all, I3arnon is right here.
CreateIndex seems to be marked obsolete in my code whereas EnsureIndex is not. Is this info definitely correct? It seems unlikely to me that they'd have switched which ones were obsoleted in a version update (so I can't believe its just that we are looking at different versions of the code).
@Chris I don't know what version are you using, but in the latest stable one EnsureIndex is obsolete. It's the same in the current version of the source code on github
@I3arnon: I'm on an older version, 1.8.3 from nuget, it seems. Still weird that they went from createIndex being obsolete in the version I have with EnsureIndex being recommended to the other way round. Thanks for taking the time to check, and indeed for pointing me at the github source. Very useful.
|
42

The overload of CreateOneAsync in the currently accepted answer is now marked as obsolete with the message "Use CreateOneAsync with a CreateIndexModel instead." Here's how you do it:

static async Task CreateIndex(string connectionString)
{
    var client = new MongoClient(connectionString);
    var database = client.GetDatabase("HamsterSchool");
    var collection = database.GetCollection<Hamster>("Hamsters");
    var indexOptions = new CreateIndexOptions();
    var indexKeys = Builders<Hamster>.IndexKeys.Ascending(hamster => hamster.Name);
    var indexModel = new CreateIndexModel<Hamster>(indexKeys, indexOptions);
    await collection.Indexes.CreateOneAsync(indexModel);
}

Comments

15

Something like this should do:

var server = MongoServer.Create("mongodb://localhost");
var db = server.GetDatabase("myapp");

var users = db.GetCollection<User>("users");

users.EnsureIndex(new IndexKeysBuilder().Ascending("EmailAddress"));

Please see the following bits in the documentation:

1 Comment

Obsolete, see I3arnon answer
6

There is an entire area on Indexing under the Definitions and Builders documentation page:

http://mongodb.github.io/mongo-csharp-driver/2.4/reference/driver/definitions/#index-keys

Example:

IndexKeysDefinition<MyModel> keys = "{ Reference: 1 }";
var indexModel = new CreateIndexModel<MyModel>(keys);
await _context.Indexes.CreateOneAsync(indexModel);

1 Comment

It is worth nothing this references an older driver version. It has changed since. At the time of writing 2.13 is the most recent: mongodb.github.io/mongo-csharp-driver/2.13/reference/driver/…
4

the easiest way to create indexes in c# is by using the driver wrapper library MongoDB.Entities. here's an example of creating a text index:

    DB.Index<Author>()
      .Key(a => a.Name, Type.Text)
      .Key(a => a.Surname, Type.Text)
      .Create();

and to do a full-text search, you simply do:

    DB.SearchText<Author>("search term");

haven't seen anything else that makes it simpler than that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.