有没有办法创建或更新 MongoDB 索引?

i3a*_*non 6 .net c# indexing mongodb mongodb-.net-driver

根据createIndexes命令的文档:

如果您使用一组选项创建索引,然后使用相同的索引字段但不同的选项发出 createIndexes,MongoDB 将不会更改选项也不会重建索引。

解决方案是删除索引并从头开始创建它,但这成本很高。

有没有一种方法可以在没有索引时创建索引,如果有具有相同选项的索引则不执行任何操作,如果选项已更改则替换索引?


这个问题最初是由Phil Barresi 在这里提出的,但后来被删除了。

i3a*_*non 1

查看驱动程序,我实现了一种CreateOrUpdateIndex扩展方法,该方法可以比较原始索引文档,如果索引选项已更改,则索引将被替换(只要索引名称保持不变):

public static WriteConcernResult CreateOrUpdateIndex(
    this MongoCollection mongoCollection,
    IMongoIndexKeys keys,
    IMongoIndexOptions options = null)
{
    if (mongoCollection.IndexExists(keys))
    {
        var indexDocument = mongoCollection.GenerateIndexDocument(keys, options);
        if (!mongoCollection.GetIndexes().RawDocuments.Any(indexDocument.Equals))
        {
            mongoCollection.DropIndex(keys);
        }
    }

    return mongoCollection.CreateIndex(keys, options);
}
Run Code Online (Sandbox Code Playgroud)

生成原始索引文档:

public static BsonDocument GenerateIndexDocument(this MongoCollection mongoCollection, IMongoIndexKeys keys, IMongoIndexOptions options)
{
    var optionsDocument = options.ToBsonDocument();
    var keysDocument = keys.ToBsonDocument();
    var indexDocument = new BsonDocument
    {
        { "ns", mongoCollection.FullName },
        { "name", GenerateIndexName(keysDocument, optionsDocument) },
        { "key", keysDocument }
    };
    if (optionsDocument != null)
    {
        indexDocument.Merge(optionsDocument);
    }

    return indexDocument;
}

public static string GenerateIndexName(IEnumerable<BsonElement> keys, BsonDocument options)
{
    const string name = "name";
    if (options != null && options.Contains(name)) return options[name].AsString;

    return string.Join("_", keys.Select(element =>
    {
        var value = "x";
        switch (element.Value.BsonType)
        {
            case BsonType.Int32: value = ((BsonInt32)element.Value).Value.ToString(); break;
            case BsonType.Int64: value = ((BsonInt64)element.Value).Value.ToString(); break;
            case BsonType.Double: value = ((BsonDouble)element.Value).Value.ToString(); break;
            case BsonType.String: value = ((BsonString)element.Value).Value; break;
        }
        return string.Format("{0}_{1}", element.Name, value.Replace(' ', '_'));
    }));
}
Run Code Online (Sandbox Code Playgroud)