Уникальные идентификаторы с mongodb

Если бы я создавал блог, я мог бы использовать заголовок блога в качестве уникального идентификатора и анализировать его по URL. Однако, что, если я хотел бы использовать числа. Вы знаете, как твиттер имеет www.twitter.com/username/statuses/9834542? Кто-нибудь нашел хороший способ сделать эту работу? использование "_id" исключено, поскольку это слишком долго.

5 ответов

Пока вы можете гарантировать уникальность, вы не обязаны использовать поставляемые по умолчанию "_id" MongoDB.

Поэтому вам решать, как вы сгенерируете это число. Если вы хотите сохранить этот номер внутри MongoDB, вы можете сохранить его в отдельной коллекции и увеличивать его для каждого нового требуемого URL-адреса.

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

Это можно сделать с помощью команды findandmodify.

Давайте рассмотрим, у нас есть специальная коллекция с именем sequences и мы хотим иметь последовательность для номеров сообщений (названный postid), вы можете использовать код, подобный следующему:

> db.runCommand ({"findandmodify": "sequence",
                   "query": { "name": "postid"},
                   "update": { $inc: { "id": 1 }},
                   "new": true });

Эта команда вернет атомарно обновленный (new) документ вместе со статусом. value поле содержит возвращенный документ, если команда выполнена успешно.

Если вы хотите добавить ограничение уникальности в собственное поле в MongoDB, используйте индекс. Затем вы можете использовать любой алгоритм хеширования, который хотите сгенерировать, и проверить его на уникальность. Пример в документации MongoDB:

db.things.ensureIndex({firstname: 1, lastname: 1}, {unique: true});

что помешает вам вставить документы с тем же именем и фамилией, что и другой документ.

Более подробная информация доступна в документации.

Я решил эту проблему, создав коллекцию 'sequence' с данными:

  • название
  • текущая стоимость

Я использую 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 (только один узел или главный / подчиненный или набор реплик) вы должны использовать правильный WriteConcern. Использование REPLICATION_SAFE в одной среде с одним экземпляром вызывает только бесконечный цикл.

Технически, идентификационный номер слишком велик, чтобы его сократить. Однако тактику можно заполнить. То есть происходит переход от шестнадцатеричного алфавита к буквенно-цифровому, что сокращает количество символов до тулизара и выглядит более красиво в 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!!!

Конечно, эта техника использует тот же идентификатор, монго.

Другие вопросы по тегам