2 votes

Pas d'exception pour les doublons avec gmongo

J'ai essayé d'insérer des doublons dans une base de données mongodb avec Groovy et Java. Java lève une exception alors que la version Groovy ignore tout simplement l'insertion du doublon.

Voici quelques exemples de code pour illustrer cela. Je fonctionne sur OsX, Mongodb version 2.4.4. Quelqu'un peut-il m'éclairer sur ce point ? Merci beaucoup !

package chapter3

import com.gmongo.GMongo
import com.mongodb.BasicDBObject
import com.mongodb.DB
import com.mongodb.DBCollection
import com.mongodb.MongoClient

class TweetArchiveWithJava {
    static void main(String[] args) {
        new TweetArchiveWithJava()
    }

    private static final int ASCENDING = 1

    TweetArchiveWithJava() {
        duplicateInsertGroovy()
        duplicateInsertJava()
    }

    def duplicateInsertJava() {
        println "Inserting duplicates with Java"
        MongoClient mongoClient = new MongoClient()
        DB db = mongoClient.getDB("twitter-archive")
        DBCollection tweets = db.getCollection("tweets")

        tweets.remove(new BasicDBObject())
        tweets.ensureIndex(new BasicDBObject("last_name", ASCENDING), "unique_index", true)

        BasicDBObject insertedRecord = new BasicDBObject("last_name", "jones")
        BasicDBObject duplicate = new BasicDBObject("last_name", "jones")
        tweets.insert(insertedRecord)
        System.out.println("Inserted first one")
        printAllTweets(tweets)
        tweets.insert(duplicate)
        System.out.println("What?!! Should not be able to insert duplicates.")

        printAllTweets(db)
    }

    private void duplicateInsertGroovy() {
        println "Inserting duplicates with Groovy"
        def mongo = new GMongo("127.0.0.1", 27017)
        def db = mongo.getDB("twitter-archive")
        DBCollection tweets = db.getCollection("tweets")

        tweets.remove([:])
        tweets.ensureIndex(new BasicDBObject("last_name", ASCENDING), "unique_index", true)

        def jones = [last_name: "jones"]
        tweets.insert(jones)
        println "Inserted first Jones"
        def duplicate = [last_name: "jones"]
        tweets.insert(duplicate)
        println "Succeeded inserting duplicate"

        println "But only one record is found"
        printAllTweets(tweets)
        println "\n"
    }

    def printAllTweets(tweets) {
        def cursor = tweets.find()
        cursor.each { println it }
    }
}

2voto

Ori Dar Points 13661

Premièrement, vous pouvez utiliser WriteResult pour l'indication des erreurs :

def jones = [last_name: "jones"]
WriteResult rs =  tweets.insert(jones)
println rs.error
//println "Inserted first Jones"
def duplicate = [last_name: "jones"]
rs = tweets.insert(duplicate)
//println "Succeeded inserting duplicate"
println rs.error

Imprimés :

null
E11000 duplicate key error index: twitter.tweets.$unique_index  dup key: { : "jones" }

La raison de cette différence est la suivante WriteConcern :

Le code de la méthode java utilise {w=1} (reconnu)

Alors que le code de la méthode groovy utilise {w=0} (normal)

Formulaire DBTCPConnector

        if ( concern.callGetLastError() ){
            return _checkWriteError( db , port , concern );
        }
        else {
            return new WriteResult( db , port , concern );
        }

et en WriteConcern :

 public boolean callGetLastError(){
    if (_w instanceof Integer)
        return (Integer) _w  > 0;
    return _w != null;
 }

Donc la méthode java appelle _checkWriteError dans les coulisses - où une exception est levée - et la méthode groovy renvoie simplement le résultat de l'écriture.

La raison pour laquelle vous avez des préoccupations différentes en matière d'écriture est le code d'initialisation :

Vous initialisez MongoClient mongoClient = new MongoClient() dans votre méthode java, qui utilise en interne WriteConcern.ACKNOWLEDGED .

Dans votre méthode groovy, le constructeur de GMongo utilise Mongo déprécié qui utilise en interne WriteConcern.NORMAL .

Si vous changez tweets.insert(duplicate) a tweets.insert(duplicate, WriteConcern.ACKNOWLEDGED) vous obtiendrez également une exception pour la méthode groovy.

0voto

tim_yates Points 63521

Pas sûr, mais que se passe-t-il si vous changez la version de groovy en :

    def jones = [last_name: "jones"] as BasicDBObject
    tweets.insert(jones)
    println "Inserted first Jones"
    def duplicate = [last_name: "jones"] as BasicDBObject
    tweets.insert(duplicate)

0voto

user2100676 Points 26

Vous pouvez également utiliser com.gmongo.GMongoClient. Il possède les mêmes constructeurs que com.mongodb.MongoClient.

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