28 votes

Puis-je utiliser String comme type d'ID pour un document mongodb ?

J'utilise java/morphia pour traiter avec mongodb. L'ObjectId par défaut n'est pas très pratique à utiliser depuis la couche Java. J'aimerais en faire un type String tout en conservant le processus de génération de clés en utilisant ObjectId, par exemple _id = new ObjectId.toString() .

Je veux savoir s'il y a des effets secondaires en procédant de cette façon ? Par exemple, cela aura-t-il un impact sur les performances de la base de données ou provoquera-t-il des conflits de clés de quelque manière que ce soit ? Est-ce que cela affectera l'environnement de sharding ...

33voto

Sergio Tulentsev Points 82783

Vous pouvez utiliser n'importe quel type de valeur pour un _id (sauf pour les tableaux). Si vous choisissez de ne pas utiliser ObjectId, vous devrez d'une manière ou d'une autre garantir l'unicité des valeurs (un casting ObjectId en chaîne de caractères fera l'affaire). Si vous essayez d'insérer une clé en double, une erreur se produira et vous devrez y remédier.

Je ne suis pas sûr de l'effet que cela aura sur le cluster sharded lorsque vous tenterez d'insérer deux documents avec le même _id dans des shards différents. Je soupçonne qu'il vous laissera insérer, mais cela vous mordra plus tard. (Je vais devoir tester cela).

Cela dit, vous ne devriez pas avoir de problèmes avec _id = (new ObjectId).toString() .

7voto

Destino Points 315

En fait, j'ai fait la même chose parce que j'avais un problème pour convertir l'ObjectId en JSON.

J'ai ensuite fait quelque chose comme

@Id
private String id;
public String getId() {
    return id();
}
public void setId(String id) {
    this.id = id;
}

Et tout a bien fonctionné jusqu'à ce que je décide de mettre à jour un document précédemment inséré, lorsque j'ai obtenu l'objet par Id, je l'ai envoyé à la page via JSON et j'ai reçu le même objet mis à jour également par post JSON et ensuite j'ai utilisé la fonction de sauvegarde du Datastore, au lieu de mettre à jour les données précédentes, il a inséré un nouveau document au lieu de mettre à jour celui qui était déjà.

Pire encore, le nouveau document avait le même ID que le document précédemment inséré, ce qui me semblait impossible.

Quoi qu'il en soit, j'ai configuré l'objet privé en tant qu'ObjectID et j'ai laissé le paramètre get set en tant que chaîne de caractères et cela a fonctionné comme prévu, mais je ne suis pas sûr que cela vous aide dans votre cas.

@Id
private ObjectId id;
public String getId() {
    return id.toString();
}
public void setId(String id) {
    this.id = new ObjectId(id);
}

6voto

Dan H Points 1889

Oui, vous pouvez utiliser une chaîne de caractères comme _id.

Je ne le recommande que si vous avez une valeur (dans le document) qui constitue naturellement une bonne clé unique. J'ai utilisé ce modèle dans une collection où il y avait une chaîne de caractères géo-tag, de la forme "xxxxyyyy" ; ce champ unique par document devait OBLIGATOIREMENT se trouver dans le document. et Je devais construire un index dessus... alors pourquoi ne pas l'utiliser comme clé ? (Cela a permis d'éviter une paire clé-valeur supplémentaire, ET d'éviter un deuxième index sur la collection puisque MongoDB construit naturellement un index sur "_id". Compte tenu de la taille de la collection, ces deux éléments ont permis de réaliser de sérieuses économies d'espace).

Cependant, d'après le ton de votre question ("les ObjectIDs ne sont pas très pratiques"), si la seule raison pour laquelle vous voulez utiliser une chaîne de caractères est que vous ne voulez pas vous embêter à trouver comment gérer proprement les ObjectIDs... Je pense que cela vaut la peine de s'y intéresser. Je suis sûr qu'ils ne posent aucun problème... une fois que vous avez compris votre problème avec eux.

Sinon : quelles sont vos options ? Allez-vous concocter des chaînes d'identification CHAQUE FOIS que vous utiliserez MongoDB à l'avenir ?

1voto

Tony Sepia Points 125

Je voudrais ajouter que ce n'est pas toujours une bonne idée d'utiliser l'ObjectID BSON généré automatiquement comme identifiant unique, s'il est transmis à l'application : il peut potentiellement être manipulé par l'utilisateur.

Les ObjectID semblent être générés de manière séquentielle, donc si vous ne mettez pas en place les mécanismes d'autorisation nécessaires, un utilisateur malveillant pourrait simplement incrémenter la valeur qu'il possède, pour accéder à des ressources auxquelles il ne devrait pas avoir accès.

UPDATE : Depuis la version 3.4+, les ObjectIDs ne sont plus générés de manière incrémentielle. Veuillez consulter 3.2 docs vs les derniers documents

Par conséquent, l'utilisation d'identifiants de type UUID fournira une couche de sécurité par l'obscurité. Bien sûr, l'autorisation (cet utilisateur est-il autorisé à accéder à la ressource demandée) est indispensable, mais vous devez être conscient de la fonctionnalité ObjectID mentionnée plus haut.

Pour obtenir le meilleur des deux mondes, générez un UUID qui correspond à la longueur de votre ObjectID (12 ou 24 caractères) et utilisez-le pour créer votre propre _id de type ObjectID.

0voto

gil.fernandes Points 5581

Vous pouvez également utiliser une chaîne de caractères comme identifiant à partir de Java. Voici un exemple de méthode et le test unitaire correspondant pour insérer un objet avec un ID de type chaîne dans une collection MongoDB :

public Document insert(String json, String collectionName) {
    MongoCollection<Document> collection = database.getCollection(collectionName);
    BasicDBObject document = BasicDBObject.parse(json);
    Document doc = new Document(document);
    collection.insertOne(doc);
    return doc;
}

@Test
void whenInsert_ShouldInsertOne() {
    final String uuid = UUID.randomUUID().toString();
    final String collection = "test_collection";
    final Document doc = app.insert(String.format("{\"_id\":\"%s\", \"name\": \"test\"}", 
        uuid), collection);
    assertThat(doc).isNotNull();
    final String json = app.getById(uuid, collection);
    assertThat(json).contains(String.format("\"_id\": \"%s\"", uuid));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X