MongoDB: вставить запись, если она не существует, игнорировать, если она существует
У меня есть серия записей MongoDB, таких как:
{"name":"Bob", "gpa":4}
{"name":"Sarah", "gpa":3}
{"name":"Jim", "gpa":2}
, я хочу принять это как есть. Если я получаю {"name":"Sarah", "gpa":4}
(другое значение GPA), я хочу просто игнорировать его. Это не похоже на логику ни update
с" upsert", установленным в yes, ни findAndModify
с "upsert."
Https://stackoverflow.com/a/3260290/514757 предлагает способ (уникальный индекс в первом поле, вставить запись, немедленно обновить второе поле), но ему уже несколько лет, и я задаюсь вопросом, нет ли лучшего способа сделать это за один шаг.
Правка:
Принятый ответ кажется отличным, но он не работает для меня! Сначала я создал индекс (это с драйвером Java):nameIndex.put("name", 1);
nameIndex.put("unique", true);
queue.ensureIndex(nameIndex);
Я вижу из командной строки, что индекс существует и уникален. Затем вставляется элемент:
DBObject person = new BasicDBObject();
person.put("name", "Bob");
person.put("score", 200000);
queue.insert(person);
Позже у элемента с наибольшей оценкой ее оценка уменьшается до нуля:
BasicDBObject reset = new BasicDBObject();
reset.put("$set", new BasicDBObject("score", 0));
DBObject dbObj = queue.findAndModify(null, new BasicDBObject("score", -1), reset);
Все это работает именно так, как задумано! Но, позже, то же самое имя может быть найдено снова, с новым счетом. Когда этот последний бит кода запускается, новый элемент создается с другой оценкой, что именно то, что я не хочу:
BasicDBObject queueable = new BasicDBObject();
queueable.put("name", "Could be Bob again, could be someone new");
queueable.put("score", 1234);
queue.insert(queueable);
Если я ищу Боба, я нахожу:
{ "_id" : ObjectId("4f5e865ad6d09315326ea0f0"), "score" : 0, "name" : "Bob" }
{ "_id" : ObjectId("4f5e8691d6d09315326ea190"), "name" : "Bob", "score" : 886 }
Была создана вторая запись, с более высокой снова счет. Имеет ли значение порядок полей? Это не похоже на то, что должно быть, и я не знаю, как это контролировать.
2 ответа:
Ваш вызов ensureIndex () не совсем корректен. Первый аргумент функции ensureIndex () содержит ключи, которые должны быть проиндексированы; параметры индекса (например, уникальность) могут быть переданы в качестве второго аргумента. Увидеть водитель документацию.
Сейчас вы пытаетесь создать неуникальный индекс для двух полей: "name"и " unique".
Попробуйте создать свой индекс следующим образом:
DBObject nameIndex = new BasicDBObject(); nameIndex.put("name",1); DBObject nameIndexOptions = new BasicDBObject(); nameIndexOptions.put("unique", true); queue.ensureIndex(nameIndex, nameIndexOptions);