2

我尝试使用 Groovy 和 Java 将重复项插入到 mongodb 数据库中。Java 引发异常,而 groovy 版本只是悄悄地忽略插入重复项。

这是一些说明这一点的示例代码。我在 OsX,Mongodb 版本 2.4.4 上运行。任何人都可以启发我吗?万分感谢!

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

3 回答 3

2

首先,您可以使用WriteResult错误指示:

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

印刷:

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

差异的原因是WriteConcern

java方法代码使用{w=1}(已确认)

而 groovy 方法代码使用{w=0}(正常)

形式DBTCPConnector

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

并在WriteConcern

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

_checkWriteError因此,java 方法在幕后调用——抛出异常——而 groovy 方法只返回写入结果。

您有不同写入问题的原因是初始化代码:

您在您的 java 方法中进行初始化MongoClient mongoClient = new MongoClient(),该方法在内部使用WriteConcern.ACKNOWLEDGED.

在您的 groovy 方法中, GMongo 构造函数使用Mongo不推荐使用的构造函数,该构造函数在内部使用WriteConcern.NORMAL.

如果你tweets.insert(duplicate)改为tweets.insert(duplicate, WriteConcern.ACKNOWLEDGED),你也会得到 groovy 方法的异常

于 2013-08-09T09:55:50.280 回答
0

不确定,但是如果将 groovy 版本更改为:

    def jones = [last_name: "jones"] as BasicDBObject
    tweets.insert(jones)
    println "Inserted first Jones"
    def duplicate = [last_name: "jones"] as BasicDBObject
    tweets.insert(duplicate)
于 2013-08-08T22:08:17.940 回答
0

您也可以使用 com.gmongo.GMongoClient。它具有与 com.mongodb.MongoClient 相同的构造函数。

于 2013-08-13T18:35:24.313 回答