Уникальные идентификаторы с mongodb - PullRequest
15 голосов
/ 30 августа 2009

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

Ответы [ 5 ]

22 голосов
/ 02 сентября 2009

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

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

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

15 голосов
/ 13 октября 2010

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

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

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

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

7 голосов
/ 27 мая 2010

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

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

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

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

4 голосов
/ 25 сентября 2010

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

  • имя
  • значение тока

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

1 голос
/ 14 января 2013

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...