Ядро Ответ
Структура ваших сообщений/Кладет для документа, который имеет поле, которое вы хотите сохранить уникальный следующим образом:
Создать view. В функции map используйте поле, которое вы хотите использовать в качестве ключа . Значение может быть ничем. Используйте функцию уменьшения, чтобы получить счет для каждого из ваших ключей. Лучшим способом (для повышения производительности) является использование встроенной функции уменьшения _count.
Сразу после PUT/POST новый документ в базу данных, захватить возвращенное id
и rev
и GET/yourdb/_design/YourApp/_view/ViewName? Группа = истинный & ключ =»значение -of-your-unique-field-from-step-1 ".
Если результат последнего GET дает вам значение счетчика, кроме , то вы только что вставили дубликат. Сразу DELETE/yourdb/id-from-step-2? Rev = rev-from-step-2.
Relax.
Грубый пример
Допустим, вы хранения пользовательских учетных записей, и вы хотите, чтобы убедиться, что адрес электронной почты является уникальным, но вы не хотите, чтобы сделать его идентификатор документа (для любой причины). Создайте представление, чтобы быстро проверить уникальность адреса электронной почты, как описано выше. Позволяет называть его email. Он имел бы функцию , возможно, похожую на это ...
function(doc) {
if(doc.type === 'account') {
emit(doc.email, 1);
}
}
И только _count
как уменьшить функцию. Если вы испустите , как и выше, _sum
также будет работать. Наличие и проверка поля type
на вашем документе, как показано выше, является просто конвенцией, но иногда мне это полезно. Если все, что вы храните, это учетные записи пользователей, вам, вероятно, это не нужно.
Теперь давайте говорить мы вставляем документ, как так ...
POST /mydb/
{
"name": "Joe",
"email": "[email protected]"
}
И CouchDB ответит что-то вроде ...
{
ok: true,
id: 7c5c249481f311e3ad9ae13f952f2d55,
rev: 1-442a0ec9af691a6b1690379996ccaba6
}
Проверьте, чтобы увидеть, если мы теперь имеем больше один [email protected] в базе данных ...
GET /mydb/_design/myapp/_view/emails/?group=true&key="[email protected]"
И CouchDB ответит чем-то вроде ...
{
rows: [
{
key: "[email protected]",
value: 1
}
]
}
Если value
ничего, кроме 1
в этом ответе, вы, вероятно, только что вставили дубликат электронной почты. Поэтому удалите документ и верните ошибку в строке . Адрес электронной почты должен быть уникальным, аналогично типичному ответу базы данных SQL или тому, что вы хотите.
Можно удалить бы что-то вроде этого ...
DELETE /mydb/7c5c249481f311e3ad9ae13f952f2d55?rev=1-442a0ec9af691a6b1690379996ccaba6
Short Обсуждение (если вы заботитесь)
Если вы едете из хорошего старого * SQL фоне, это будет казаться неправильным и странным. Перед тем, как вы переверните, рассмотрите эти моменты. Наличие ограничения на поле, такое как уникальность или что-то еще, подразумевает схему . CouchDB is schemaless. Исходя из * SQL означает, что вам придется изменить то, как вы думаете. ACID и Locks - не единственный способ. CouchDB поставляется с большой гибкостью и мощностью. Как вы используете это, чтобы получить то, что вы хотите, будет зависеть от деталей вашего прецедента и насколько хорошо вы можете избежать ограничений традиционного мышления реляционной базы данных.
Причина, по которой я иногда реализую уникальность таким образом, заключается в том, что мне очень нравится Couchy. Если вы думаете о том, как CouchDB работает с обработкой конфликтов обновления и т. Д., Этот подход следует за тем же потоком. Мы сохраняем документ, который мы даем, затем проверяем, уникально ли наше поле. Если нет, возьмите этот документ, который мы просто вставили с помощью удобного ручка, который у нас есть на нем, и сделаем что-то, чтобы разрешить необходимость уникальности, например, удалить его.
Возможно, вас соблазнит приведенный выше пример, чтобы проверить уникальность адреса электронной почты до вы POST
документ. Быть осторожен!!Если происходит несколько событий, возможно, что другой документ с тем же адресом электронной почты может быть вставлен в базу данных в момент после, вы проверяете, существует ли это письмо, но до вы делаете свой POST
! Это оставит вас с дублирующимся адресом электронной почты.
Нет ничего плохого в том, что вы также проверите чек на адрес электронной почты перед вами POST
. Например, это хорошая идея, если ваш пользователь заполняет форму, и вы можете изменить значение поля электронной почты в базе данных. Вы можете предварительно предупредить пользователя о существовании адреса электронной почты или о недопущении подачи и т. Д. Однако во всех случаях вам необходимо также проверить уникальность после вы POST
документ. Затем реагируйте при необходимости. С точки зрения стороны пользовательского интерфейса вышеописанные этапы выглядят не иначе, как результат, полученный от традиционной базы данных SQL *, налагающей ограничения на уникальность.
Возможно, что-то пошло не так? Да. Учти это. Предположим, [email protected] еще не существует в базе данных. Два документа поступают почти одновременно, чтобы быть сохраненными в базе данных. Doc является POSTed
, то Doc B является POSTed
, но прежде чем мы сможем проверить уникальность для DocPOST
. Итак, теперь, когда мы выполняем проверку уникальности для Doc APOST
, мы видим, что в базе данных дважды в базе данных [email protected]. Итак, мы удалим его и сообщим о проблеме. Но скажем, прежде чем мы сможем удалить Doc A, проверка уникальности для Doc B также происходит, получая одинаковое значение для [email protected]. Теперь и POSTs
будут отклонены, хотя [email protected] изначально не было в базе данных! Другими словами, если два приложения с подходящим значением приходят в ваше приложение почти одновременно, его возможно, что они могут видеть друг друга POSTs
и ошибочно заключают, что значение, которое они переносят, уже находится в базе данных! Мы не можем действительно предотвратить это, потому что нет традиционного стиля RDB , блокирующего в CouchDB. Но в обмен на эту небольшую цену мы получаем репликацию мастер-мастера и тонну других интересных вещей. Я возьму это! И если это огромная проблема для вашей реализации, вы можете попытаться решить ее, используя какой-то механизм повтора и т. Д.
Наконец, CouchDB действительно является жемчужиной базы данных, но не просто возьмите это и ожидать, что это будет пуленепробиваемый подход. Многое будет зависеть от деталей вашего конкретного приложения.
Да, это решение, но лично я предпочитаю блокировку с Редисом. Такие решения выглядят странно, когда разработчики приходят из мира РСУБД. CouchDB отличается от РСУБД, но должны ли мы отказаться от всех существующих практик? Нет ACID и замков, но без всего этого невозможно расслабиться и просто написать приложения. CouchDB не хватает ключевых функций, и это печально. – Sam
Хранение уникального значения перед добавлением его в идентификатор документа упрощает добавление значений, которые могут иметь специальные символы. –
Обратите внимание, что если вы планируете держать вещи с несколькими мастерами, пункт 2.будет ** не ** сбой, если ключ уже не существует на * текущем * узле. Ключи уникальны только на узле, в котором они существуют. Проверьте ответ Раффи М. на простое кластерное решение этой проблемы. – user1973386