2009-08-29 16 views
15

Si estuviera creando un blog, podría usar el título del blog como el identificador único y analizarlo a través de la URL. Sin embargo, ¿y si quisiera usar números? ¿Sabes cómo Twitter tiene www.twitter.com/username/statuses/9834542? ¿Alguien ha descubierto una buena manera de hacer que esto funcione? usar "_id" está fuera de discusión ya que es demasiado largo.ID únicos con mongodb

+0

Puede hacer un hash md5 (o cualquiera) de la url y almacenarlo en el lugar de _id. –

Respuesta

22

Mientras pueda garantizar la exclusividad, no está obligado a utilizar los suministros de MongoDB predeterminados "_id".

Por lo tanto, depende de usted cómo genera este número. Si desea almacenar este número dentro de MongoDB, puede almacenarlo en una colección separada e incrementarlo para cada nueva URL requerida.

Incrementando un campo se logra utilizando the $inc verb, o tal vez quiera echar un vistazo a cómo MongoDB puede atomically update o incrementar un valor.

+0

Como dijo Alan, puede proporcionar su propia identificación. Entonces la pregunta es cómo puedes generarlo de manera única. Lo más fácil es si tiene algún servidor de secuencia (es decir, algo que diseña un número y luego se incrementa, manteniendo un bloqueo para que ocurra de manera atómica.) Este servidor de secuencia podría usar un único registro mongo por secuencia –

7

Si desea agregar una restricción de exclusividad a su propio campo en MongoDB, use un índice. Luego puede usar cualquier algoritmo hash que quiera generar el número y probarlo para que sea único. El ejemplo en la documentación MongoDB es

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

que impedir que se inserte documentos con el mismo nombre y apellido como otro documento.

Más información está disponible en el documentation.

4

He resuelto este problema mediante la creación de la colección 'secuencia' con los datos:

  • nombre
  • valor currurt

estoy usando Morhpia, también lo han hecho DAO para ello. Pero puedes hacerlo sin Morhpia también. La idea es usar $ atomic (probablemente se puede omitir debido a la actualización de 1 instancia solamente) y $inc modificador operador.

Secuencia

@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 
} 

Método en 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; 
} 

Dependiendo de la configuración MongoDB (un nodo sólo o maestro/esclavo o conjunto de réplicas) usted tiene que utilizar WriteConcern correcta. Usar REPLICATION_SAFE en un entorno con una sola instancia solo causa un bucle infinito.

+0

¿Qué idioma es este? :) Hits my ¡ojo! – asyncwait

15

Se puede hacer utilizando el comando findandmodify.

Vamos a considerar que tenemos una colección especial llamado sequences y queremos tener una secuencia de números de correos (nombre postid), se puede utilizar código similar al siguiente:

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

Este comando devolverá atómicamente el actualizan (new) documento junto con el estado. El campo value contiene el documento devuelto si el comando se completó correctamente.

+0

¿Cómo se puede hacer esto en un entorno fragmentado? – BlitzKrieg

+0

@BlitzKrieg, según la documentación: "* findandmodify * se comportará igual cuando se llame a través de un mongos, siempre y cuando la colección que está modificando no esté marcada. Si la colección está fragmentada, la consulta debe contener la clave del fragmento". Entonces, ¿no destruye la colección 'sequences'? –

+0

Entendido @Hubert ... ¡Gracias! – BlitzKrieg

1

Técnicamente, el número de ID es demasiado grande para acortarlo.Sin embargo, se puede llenar una táctica. Eso está pasando de hexadecimal a alfanumérico, reduciendo así el número de caracteres para tulizar y se ve más hermoso en la URL. Realmente serví muy bien ... aquí está

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!!! 

Por supuesto, esta técnica usa la misma identificación, mongo.

Cuestiones relacionadas