2016-03-03 2 views
2

У меня есть схемы MongoDB для пользователей, который выглядит примерно так:MongoDB Необязательный Уникальный индекс

{ 
    userId: "some-string", 
    anonymousId: "some-other-string", 
    project: {"$oid": "56d06bb6d9f75035956fa7ba"} 
} 

Пользователи должны иметь либо userId или anonymousId. Поскольку пользователи принадлежат к проекту, модель также имеет ссылку под названием project, которая ссылается на коллекцию проекта.

Любой userId или anonymousId значение должно быть уникальным для каждого проекта, поэтому я создал два составных индексов следующим образом:

db.users.createIndex({ "userId": 1, "project": 1 }, { unique: true }) 
db.users.createIndex({ "anonymousId": 1, "project": 1 }, { unique: true }) 

Однако, как не как userId и anonymousId должны быть предоставлены, но только как один из них, MongoDB выбрасывает ошибку duplicate key для значений null (например, если есть второй пользователь с предоставленным анонимным, но без пользователя).

Поэтому я попытался добавить флаг sparse: true в составные индексы, но это, очевидно, работает только в том случае, если оба поля пустые. Я также попытался добавить разреженный флаг только к полям, а не к составным индексам, но это тоже не сработает.

Для примера, скажем, у меня есть следующие три пользователей в коллекции:

{ userId: "user1", anonymousId: null, project: {"$oid": "56d06bb6d9f75035956fa7ba"}} 

{ userId: "user2", anonymousId: "anonym", project: {"$oid": "56d06bb6d9f75035956fa7ba"}} 

{ userId: "user3", anonymousId: "random", project: {"$oid": "56d06bb6d9f75035956fa7ba"}} 

Следующие должно быть возможно:

  • Я хочу, чтобы иметь возможность вставить другой пользователь {userId: "user4", anonymousId: null} для того же проекта (без получения повторяющейся ключевой ошибки)
  • Однако, если я попытаюсь вставить другого пользователя с {userId: "user3"} или другим пользователем с {anonymousId: "random"}, то должна быть дублика te ключевая ошибка

Как еще я могу это достичь?

+0

Какую версию MongoDB вы используете? – Saleem

+0

Я использую 3.0.9. Вы спрашиваете из-за частичных индексов? – benjiman

+0

Действительно. Это намерение и решит массу ваших проблем. Я предлагаю обновить движок базы данных, если это возможно. – Saleem

ответ

2

Если вы используете MongoDB 3.2, вы можете использовать уникальный неполный индекс вместо разреженного индекса.

Частичный индекс фактически рекомендуется более разреженным индексом

Пример

db.users.createIndex({ "userId": 1, "project": 1 }, 
{ unique: true, partialFilterExpression:{ 
    userId: { $exists: true, $gt : { $type : 10 } } } }) 

db.users.createIndex({ "anonymousId": 1, "project": 1 }, 
{ unique: true, partialFilterExpression:{ 
    anonymouseId: { $exists: true, $gt : { $type : 10 } } } }) 

В приведенном выше примере, уникальный индекс будет создан только тогда, когда userId присутствует и не содержит нулевое значение. То же самое относится и к anonymousId.

См. https://docs.mongodb.org/manual/core/index-unique/#unique-partial-indexes

+0

Да, я знаю, но, к сожалению, мне нужно использовать версию 3.0.9. Однако как вы это сделаете с помощью частичного индекса? – benjiman

+0

Ну, в этом случае у вас есть только один вариант, который я вижу выше, опубликованный profesor79. Создайте составной индекс для всех трех полей. – Saleem

+0

Не могли бы вы отредактировать свой ответ, чтобы привести пример создания уникального частичного индекса в этом случае? – benjiman

1

индекс а, с - не может быть редкими, как это уникальный .....

индекс б, в - не может быть редкими, как это уникальный .....

насчет индекса а, б , c?

db.benjiman.insert ({идентификатор пользователя: "некоторые строка", anonymousId: "некоторые-другой-строка", проект: { "_oid": "56d06bb6d9f75035956fa7ba"}} )

db.benjiman.insert ({идентификатор пользователя: "некоторые-строка2", проект: { "_oid": "56d06bb6d9f75035956fa7ba"}})

db.benjiman.insert ({anonymousId: "некоторые-другие-строка2", проект: {"_oid": "56d06bb6d9f75035956fa7ba"}})

db.benjiman.createIndex({ "userId": 1, "anonymousId": 1, "project": 1 }, { unique: true }) 
+0

Я тоже думал об этом, но проблема с этим подходом заключается в том, что он позволяет вставлять один и тот же userId, например, если имеется другой анонимный идентификатор. – benjiman

+0

ok, теперь у вас больше изображение, давайте поговорим здесь http://chat.stackoverflow.com/rooms/104903/mongo-queries-issues – profesor79

Смежные вопросы