2009-08-29 25 views
15

Se dovessi creare un blog, potrei usare il titolo del blog come identificativo univoco e analizzarlo tramite l'URL. Tuttavia, cosa succede se volevo usare i numeri. Sai come Twitter ha www.twitter.com/username/statuses/9834542? Qualcuno ha capito un bel modo di fare questo lavoro? usare "_id" è fuori questione poiché è troppo lungo.ID univoci con mongodb

+0

È possibile eseguire un hash MD5 (o qualsiasi) dell'URL e memorizzarlo nel posto di _id. –

risposta

22

Finché è possibile garantire univocità, non si è obbligati a utilizzare i materiali di consumo "_id" MongoDB predefiniti.

Quindi, dipende da te come si genera questo numero. Se desideri memorizzare questo numero all'interno di MongoDB, puoi archiviarlo in una raccolta separata e incrementarlo per ogni nuovo URL richiesto.

L'incremento di un campo viene ottenuto utilizzando the $inc verb oppure è possibile dare un'occhiata a come MongoDB può atomically update o incrementare un valore.

+0

Come ha detto Alan, è possibile fornire il proprio ID. Quindi la domanda è come si può generare in modo univoco. Il più semplice è se avessi un server di sequenze (cioè qualcosa che restituisce un numero e poi incrementa, tenendo premuto un lucchetto in modo che avvenga atomicamente Questo server di sequenza potrebbe utilizzare un singolo record mongo per sequenza –

7

Se si desidera aggiungere un vincolo di unicità al proprio campo in MongoDB, utilizzare un indice. Quindi è possibile utilizzare qualsiasi algoritmo di hashing che si desidera generare il numero e verificarlo per univocità. L'esempio nella documentazione MongoDB è

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

che vi impedirà di inserire i documenti con lo stesso nome e cognome come un altro documento.

Ulteriori informazioni sono disponibili nello documentation.

4

ho risolto questo problema con la creazione di raccolta 'sequenza' con i dati:

  • nome
  • valore currurt

sto usando Morhpia, in modo da avere DAO per esso. Ma puoi farlo anche senza Morhpia. L'idea è di usare $ atomic (probabilmente può essere omesso a causa dell'aggiornamento solo di 1 istanza) e dell'operatore di modifica $inc.

Sequenza

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

metodo su 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; 
} 

A seconda della configurazione MongoDB (un nodo solo o master/slave o set di repliche) si deve utilizzare corretta WriteConcern. L'utilizzo di REPLICATION_SAFE in un ambiente con un'istanza causa solo un ciclo infinito.

+0

Che lingua è? :) Colpisce il mio occhio! – asyncwait

15

È possibile utilizzare il comando findandmodify.

Consideriamo abbiamo una collezione speciale di nome sequences e vogliamo avere una sequenza di numeri postali (denominate postid), è possibile utilizzare codice simile a questo:

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

Questo comando restituirà atomicamente l'aggiornamento (new) insieme allo stato. Il campo value contiene il documento restituito se il comando è stato completato correttamente.

+0

Come si fa a fare questo lavoro in un ambiente più complesso? – BlitzKrieg

+0

@BlitzKrieg, come da documentazione: "* findandmodify * si comporterà allo stesso modo quando viene chiamato attraverso un mongos purché la raccolta che sta modificando sia non criptata.Se la raccolta è sharded, la query deve contenere la chiave shard." Quindi, non tagliare la collezione 'sequenze'? –

+0

Ho capito @Hubert ... Grazie !! – BlitzKrieg

1

Tecnicamente, il numero ID è troppo grande per accorciarlo.Tuttavia, una tattica può essere riempita. Questo sta passando da esadecimale alfanumerico, riducendo così il numero di caratteri in tulizar e sembra più bello nell'URL. Ho davvero servito molto bene ... ecco

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

Ovviamente questa tecnica utilizza lo stesso id, mongo.

Problemi correlati