web-dev-qa-db-ja.com

C#でMongoDBの一意のキーを作成する

ユニークなフィールドEmailAddressを作成するために戦っています。フォーラムでインデックスを作成する必要があることはすでに確認しましたが、今のところうまくいきませんでした。誰かがコード例を持っていますか?保存/呼び出しのたびにインデックスを作成する必要がありますか、それとも1回だけ作成すれば十分ですか?

私はこのコードを試しました:

DB.GetCollection<User>(Dbname)
    .EnsureIndex(new IndexKeysBuilder()
        .Ascending("EmailAddress"), IndexOptions.SetUnique(true));

DB.GetCollection<User>(Dbname).Save(user, SafeMode.True);

私のUserモデルは次のようになります。

public class User
{
    [Required(ErrorMessage = "Email Required")]
    public string EmailAddress { get; set; }

    public ObjectId Id { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}
26
Uter1007

一意のインデックスを作成する必要があるのは1回だけです。その後、重複する電子メールアドレスを含むドキュメントの挿入は失敗します。次に例を示します。

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

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

users.EnsureIndex(new IndexKeysBuilder()
    .Ascending("EmailAddress"), IndexOptions.SetUnique(true));

var user1 = new User { EmailAddress = "[email protected]" };
var user2 = new User { EmailAddress = "[email protected]" };

try
{
    users.Save(user1, WriteConcern.Acknowledged);
    users.Save(user2, WriteConcern.Acknowledged);  // <-- throws MongoSafeModeException
}
catch (MongoSafeModeException ex)
{
    Console.WriteLine(ex.Message);
}
28
Chris Fulstow

PreventIndex()は、C#mongoドライバーバージョン2.0仕様に従って非推奨/廃止されました: http://api.mongodb.org/csharp/current/html/M_MongoDB_Driver_MongoCollection_EnsureIndex_2.htm

非同期で2.0コードを使用する方法

var mongoClient = new MongoClient("connection");
var db = mongoClient.GetDatabase("database");

var options = new CreateIndexOptions() { Unique = true };
var field = new StringFieldDefinition<User>("EmailAddress");
var indexDefinition = new IndexKeysDefinitionBuilder<User>().Ascending(field);
await db.GetCollection<Users>("users").Indexes.CreateOneAsync(indexDefinition, options);

非文字列インデックスの場合:

   var options = new CreateIndexOptions() { Unique = true };
   IndexKeysDefinition<Foo> keyCode = "{ Code: 1 }";
   var codeIndexModel = new CreateIndexModel<Foo>(keyCode, options);
21
kennydust

あなたのコードは正しく見えます。比較するための完全に実行されているプログラムは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace TestEnsureIndexOnEmailAddress {
    public class User {
        public ObjectId Id;
        public string FirstName;
        public string LastName;
        public string EmailAddress;
    }

    public static class Program {
        public static void Main(string[] args) {
            var server = MongoServer.Create("mongodb://localhost/?safe=true");
            var database = server["test"];
            var users = database.GetCollection<User>("users");
            if (users.Exists()) { users.Drop(); }

            users.EnsureIndex(IndexKeys.Ascending("EmailAddress"), IndexOptions.SetUnique(true));
            var john = new User { FirstName = "John", LastName = "Smith", EmailAddress = "[email protected]" };
            users.Insert(john);
            var joe = new User { FirstName = "Joe", LastName = "Smith", EmailAddress = "[email protected]" };
            users.Insert(joe); // should throw exception
        }
    }
}

Mongo Shellを使用して、インデックスが作成されたことを確認することもできます。

> db.users.getIndexes()
[
        {
                "name" : "_id_",
                "ns" : "test.users",
                "key" : {
                        "_id" : 1
                },
                "v" : 0
        },
        {
                "_id" : ObjectId("4de8152ee447ad2550e3b5fd"),
                "name" : "EmailAddress_1",
                "ns" : "test.users",
                "key" : {
                        "EmailAddress" : 1
                },
                "unique" : true,
                "v" : 0
        }
]
>
8
Robert Stam

以下の2.8の時点で、インデックスを作成する方法です。最後の2行に注意してください。 CreateOneAsync(indexDefinition、options)は廃止されました。

var mongoClient = new MongoClient("connection");
var db = mongoClient.GetDatabase("database");

var options = new CreateIndexOptions() { Unique = true };
var field = new StringFieldDefinition<User>("EmailAddress");
var indexDefinition = new IndexKeysDefinitionBuilder<User>().Ascending(field);

var indexModel = new CreateIndexModel<User>(indexDefinition,options);
await db.GetCollection<Users>("users").Indexes.CreateOneAsync(indexModel);
0
nandithakw

MongoDB.Entities を使用した作業プログラムは次のとおりです(免責事項:私は作成者です)

_using System;
using MongoDB.Driver;
using MongoDB.Entities;

namespace StackOverflow
{
    public class User : Entity
    {
        public string Name { get; set; }
        public string EmailAddress { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new DB("test");

            DB.Index<User>()
              .Options(o => o.Unique = true, o => o.Background = false)
              .Key(u => u.EmailAddress, Type.Ascending)
              .Create();

            var user1 = new User { Name = "First User", EmailAddress = "[email protected]" };
            user1.Save();

            try
            {
                var user2 = new User { Name = "Second User", EmailAddress = "[email protected]" };
                user2.Save();
            }
            catch (MongoWriteException x)
            {
                Console.WriteLine(x.Message);
                Console.ReadKey();
            }
        }
    }
}
_

同じ電子メールアドレスで2番目のユーザーを作成しようとすると、次の例外が発生します。

A write operation resulted in an error. E11000 duplicate key error collection: test.User index: EmailAddress(Asc) dup key: { : "[email protected]" }

0
Ryan Gunner