Мангуст уникальный индекс не работает!



Я пытаюсь позволить MongoDB обнаружить повторяющееся значение на основе его индекса. Я думаю, что это возможно в MongoDB, но через обертку Мангуста вещи, кажется, сломаны. Так что для чего-то вроде этого:



User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})


Я могу сохранить 2 пользователей с той же электронной почтой. Штопать.



тот же вопрос был выражен здесь:https://github.com/LearnBoost/mongoose/issues/56, но эта нить стара и ведет в никуда.



на данный момент, я вручную делаю вызовите БД, чтобы найти пользователя. Этот вызов не стоит дорого, так как" электронная почта " индексируется. Но все равно было бы неплохо, чтобы это было обработано изначально.



есть ли у кого-нибудь решение для этого?

896   13  

13 ответов:

Упс! Вам просто нужно перезапустить монго.

Упс! Вам просто нужно перезапустить монго.

и переиндексировать тоже !

в тестировании, я просто сделал:

mongo <db-name>
> db.dropDatabase()

хотя если у вас есть важные данные там, вы наверно просто надо:

mongo <db-name>
> db.<collection-name>.reIndex()

я столкнулся с той же проблемой: я добавил уникальное ограничение для

такое поведение происходит также, если вы оставили некоторые дубликаты в Mongo. Мангуст будет пытаться создать их в монго, когда ваше приложение запускается.

чтобы предотвратить это, вы можете обработать эту ошибку так :

yourModel.on('index', function(err) {
  if (err?) {
    console.error err
  }
);

хорошо, я смог решить это из mongoshell, добавив индекс в поле и установив уникальное свойство:

db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});

оболочка должна реагировать следующим образом:

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

теперь, чтобы проверить быстро от mongoshell:

var doc = {fieldName: 'abc'};
db.<collectionName>.insert(doc)

должны дать: WriteResult({ "nInserted" : 1 })

но при повторении снова:

db.<collectionName>.insert(doc)

даст:

WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1  dup key: { : \"[email protected]\" }"
    }
})

согласно документации:https://docs.mongodb.com/v2.6/tutorial/modify-an-index/

изменить существующий индекс, необходимо удалить и повторно создать индекс.

НЕ ПЕРЕЗАПУСКАЙТЕ MONGO !

1 - падение сбора

db.users.drop()

2-переиндексировать таблицу

db.users.ensureIndex({email: 1, type: 1}, {unique: true})

Мангуст немного свободен при применении уникальных индексов с уровня приложения; поэтому предпочтительно либо применять ваши уникальные индексы из самой базы данных с помощью Mongo cli, либо явно сказать Мангусту, что вы серьезно относитесь к unique индекс, написав следующую строку кода сразу после вашего UserSchema:

UserSchema.index({ username: 1, email: 1 }, { unique: true});

это приведет к применению уникального индекса на обоих username и email поля в вашей UserSchema. Овации.

вы также можете решить эту проблему путем удаления индекса;

предположим, вы хотите удалить уникальный индекс из коллекции users и поле username типа такого:

db.users.dropIndex('username_1');

Мангуст-уникальный-оценщику

как использовать этот плагин:

1) npm install --save mongoose-unique-validator

2) в вашей схеме следовать этому руководству:

// declare this at the top
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

// exampleSchema = mongoose.Schema({}) etc...

exampleSchema.plugin(uniqueValidator);

// module.exports = mongoose.model(...) etc....

3) методы мангуста

при использовании таких методов, как findOneAndUpdate вам нужно будет передать этот объект конфигурации:

{ runValidators: true, context: 'query' }

ie. User.findOneAndUpdate(
      { email: '[email protected]' },
      { email: '[email protected]' },
      { runValidators: true, context: 'query' },
      function(err) {
        // ...
    }

4) дополнительные опции

  1. случае бесчувственный

    используйте параметр uniqueCaseInsensitive в своей схеме

    ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }

  2. пользовательские сообщения об ошибках

    ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });

теперь вы можете добавить/удалить уникальное свойство в свои схемы, не беспокоясь о перезапуске mongo, удалении баз данных или создании индексов.

предостережения (из документов):

потому что мы полагаемся на асинхронные операции чтобы проверить, существует ли документ в базе данных, можно одновременно выполнить два запроса, оба получить 0 назад, а затем оба вставить в MongoDB.

за пределами автоматической блокировки коллекции или принудительного одиночного соединения нет реального решения.

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

Если таблица / коллекция пуста, то создайте уникальный индекс для поля:

db.<collection_name>.createIndex({'field':1}, {unique: true})

Если таблица / коллекция не пуста, то удалите коллекцию и создайте индекс:

db.<collection_name>.drop()
db.<collection_name>.createIndex({'field':1}, {unique: true})

теперь перезапустите mongoDB.

новый ответ: нет необходимости перезапускать mongodb вообще, если colleciton уже имеет одноименные индексы, мангуст не будет воссоздавать ваши индексы снова, таким образом, падение существующие индексы выставкой, во-первых, и теперь, когда вы запустите Мангуст, он создаст новый индекс, выше процесс решил мою проблему.

Я сделал что-то вроде этого:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const FooSchema = new Schema({
   name: { type: String, required: true, index: true, unique: true }
});

const Foo = mongoose.model('Foo', FooSchema);

Foo.createIndexes();

module.exports = Foo

добавил Foo.createIndexes() строка b. c. я получал следующее предупреждение об устаревании при запуске кода:

(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

Я не уверен, если Foo.createIndexes() асинхронно, но AFAIK вещи, кажется, работает нормально

Если вы используете опцию autoIndex: false в методе соединения, как это:

mongoose.connect(CONNECTION_STRING, { autoIndex: false });

Попробуйте удалить это. Если это не сработает, попробуйте перезапуск mongodb как многие предложили в этой теме.

Comments

    Ничего не найдено.