Уникальные идентификаторы с mongodb
Если бы я строил блог, я мог бы использовать заголовок блога как уникальный идентификатор и проанализировать его через URL. Однако, что, если бы я хотел использовать числа. Вы знаете, как твиттер имеет www.twitter.com/username/statuses/9834542? Кто-нибудь придумал хороший способ сделать эту работу? использование "_id" не может быть и речи, поскольку оно слишком длинное.
Ответы
Ответ 1
Пока вы можете гарантировать уникальность, вы не можете использовать по умолчанию "_id" поставки MongoDB.
Таким образом, вам нужно, как вы генерируете это число. Если вы хотите сохранить этот номер внутри MongoDB, вы можете сохранить его в отдельной коллекции и увеличить его для каждого нового URL-адреса.
Приращение поля достигается с помощью $inc
verb, или вы можете посмотреть, как MongoDB может атомизировать обновление или увеличивать значение.
Ответ 2
Это можно сделать, используя команду findandmodify.
Давайте рассмотрим, что у нас есть специальный набор с именем sequences
, и мы хотим иметь последовательность для почтовых номеров (с именем postid
), вы можете использовать код, похожий на этот:
> db.runCommand( { "findandmodify" : "sequences",
"query" : { "name" : "postid"},
"update" : { $inc : { "id" : 1 }},
"new" : true } );
Эта команда будет автоматически возвращать обновленный (new
) документ вместе со статусом. Поле value
содержит возвращенный документ, если команда успешно завершена.
Ответ 3
Если вы хотите добавить ограничение уникальности в свое поле в MongoDB, используйте индекс. Затем вы можете использовать любой алгоритм хеширования, который вы хотите сгенерировать, и проверить его на уникальность. Пример в документации MongoDB:
db.things.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
что помешает вам вставить документы с таким же именем и фамилией в качестве другого документа.
Дополнительная информация доступна в документации.
Ответ 4
Я решил эту проблему, создав "последовательность" коллекции с данными:
Я использую Morhpia, так что для этого DAO. Но вы можете сделать это и без Морхпии.
Идея заключается в использовании $atomic (возможно, его можно исключить из-за обновления только 1 экземпляр) и $inc.
Последовательность
@Entity(value = "sys_sequence", noClassnameStored = true)
public class SequenceM {
/**
* Names of entity
*/
public static enum Entity {
USER,
CAPABILITY_HISTORY;
public String getEntityName() {
return this.name().toLowerCase();
}
}
@Id
private ObjectId uid;
@Property
@Indexed(unique = true)
private String name;
@Property
private Long value;
//..getters/setters/etc
}
Метод на SequenceDAO:
@NotNull
public Long nextValue(final @NotNull SequenceM.Entity entity) {
final DB db = this.ds.getDB();
final WriteConcern writeConcern = getWriteConcern();
//optimization for JVM instance
synchronized(entity) {
do {
SequenceM sequence = findOne("name", entity.getEntityName());
final DBObject q = BasicDBObjectBuilder.start().add("name", entity.getEntityName()).add("value", sequence.getValue()).add("$atomic", 1).get();
final DBObject o = BasicDBObjectBuilder.start().add("$inc", BasicDBObjectBuilder.start().add("value", 1).get()).get();
WriteResult writeResult = db.getCollection("sys_sequence").update(q, o, false, true, writeConcern);
if(writeResult.getN() == 1) {
return sequence.getValue() + 1;
}
} while(true);
}
}
/**
* Determining writing concern basing on configuration
*/
private WriteConcern getWriteConcern() {
return isOneNodeOnly ? WriteConcern.SAFE : REPLICATION_SAFE;
}
В зависимости от конфигурации MongoDB (только один node или мастер/ведомый или набор реплик) вы должны использовать правильный WriteConcern. Использование REPLICATION_SAFE в одной среде с одним экземпляром вызывает только бесконечный цикл.
Ответ 5
Технически, идентификационный номер слишком велик, чтобы сократить его. Однако тактика может быть заполнена. Это переход от Hex к буквенно-цифровому, что уменьшает количество символов до tulizar и выглядит более красивым в Url. Я действительно очень хорошо служил... здесь
function encode(hex) {
return new Buffer(hex, 'hex').toString('base64').replace('+', '-').replace('/', '_');
};
function decode(NoHex) {
return new Buffer( NoHex.replace('-','+').replace('_','/'), 'base64').toString('hex');
};
IdString= MyDoc._id.toString();
Idencode = encode( IdString ) // 16 Caracters a-Z and 0-9
console.log( IdEncode ); //You see That 'aqswedasdfdsadsf'
IdDecode = decode( IdEncode );
IdDecode === IdString // Is true!!!
Конечно, этот метод использует тот же идентификатор, mongo.