使用MongoDb创建索引

17

我是MongoDB的初学者,正在尝试一些东西。 我想要存储URL并避免重复的URL,因此我在url上创建了一个唯一索引。 就像这样:

collection.createIndex(new BasicDBObject("url", type).append("unique", true));

但是每次我启动程序时,索引都会被重新创建,是吗?

因为现在我的程序只插入一个url "http://site.com",如果我重新启动程序,这个url会再次插入,就好像没有索引一样。

每次创建索引是处理索引的错误方式吗?

这是我的代码示例:

mongo.getCollection().ensureIndex(new BasicDBObject("url", 1).append("unique", "true"));

mongo.getCollection().insert(new BasicDBObject("url", "http://site.com").append("crawled", 0));

mongo.getCollection().insert(new BasicDBObject("url", "http://site.com").append("crawled", 0));

输出结果为:

{ "_id" : { "$oid" : "50d627cf44ae5d6b5e9cf106"} , "url" : "http://site.com" , "crawled" : 0}
{ "_id" : { "$oid" : "50d627cf44ae5d6b5e9cf107"} , "url" : "http://site.com" , "crawled" : 0}

谢谢

编辑:

这是我的Mongo类,用于处理MongoDB import java.net.UnknownHostException; import java.util.List; import java.util.Set;

import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.MongoClient;

public class Mongo {

    private MongoClient mongoClient;
    private DB db;
    private DBCollection collection;
    private String db_name;

    public Mongo(String db){

        try {
            mongoClient = new MongoClient( "localhost" , 27017 );

            this.db = mongoClient.getDB(db);
            this.db_name = db;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

    }

    public void drop(){
        mongoClient.dropDatabase(db_name);
    }

    public void listCollections(){
        Set<String> colls = db.getCollectionNames();

        for (String s : colls) {
            System.out.println(s);
        }
    }

    public void listIndex(){
         List<DBObject> list = collection.getIndexInfo();

            for (DBObject o : list) {
                System.out.println("\t" + o);
            }
    }

    public void setCollection(String col){
        this.collection = db.getCollection(col);
    }

    public void insert(BasicDBObject doc){

        this.collection.insert(doc);

    }

    public DBCollection getCollection(){
        return collection;
    }

    public void createIndex(String on, int type){
        collection.ensureIndex(new BasicDBObject(on, type).append("unique", true));
    }


}

这是处理程序的类:

public class Explorer {

    private final static boolean DEBUG = false;
    private final static boolean RESET = false;

    private Mongo mongo;

    private String host;

    public Explorer(String url){
        mongo = new Mongo("explorer");
        mongo.setCollection("page");

        if (RESET){
            mongo.drop();
            System.out.println("Set RESET to FALSE and restart the program.");
            System.exit(1);
        }

        if (DEBUG) {
            mongo.listCollections();

        }

        this.host = url.toLowerCase();



        BasicDBObject doc = new BasicDBObject("url", "http://site.com").append("crawled", 0);

        mongo.getCollection().ensureIndex(new BasicDBObject("url", 1).append("unique", true));

        mongo.getCollection().insert(new BasicDBObject("url", "http://site.com").append("crawled", 0));

        mongo.getCollection().insert(new BasicDBObject("url", "http://site.com").append("crawled", 0));




        process();
    }


    private void process(){


        BasicDBObject query = new BasicDBObject("crawled", 0);

        DBCursor cursor = mongo.getCollection().find(query);

        try {
            while(cursor.hasNext()) {
                System.out.println(cursor.next());
            }
        } finally {
            cursor.close();
        }

    }
}
5个回答

22

您需要将唯一值作为布尔值 true 而不是字符串传递,并且它是选项的第二个参数:

...ensureIndex(new BasicDBObject("url", 1), new BasicDBObject("unique", true));

此外,我使用Mongo解释器手动测试了它:

> db.createCollection("sa")
{ "ok" : 1 }
> db.sa.ensureIndex({"url":1},{unique:true})
> db.sa.insert({url:"http://www.example.com", crawled: true})
> db.sa.insert({url:"http://www.example.com", crawled: true})
E11000 duplicate key error index: test.sa.$url_1  dup key: { : "http://www.example.com" }
> db.sa.insert({url:"http://www.example2.com/", crawled: false})
> db.sa.insert({url:"http://www.example.com", crawled: false})
E11000 duplicate key error index: test.sa.$url_1  dup key: { : "http://www.example.com" }
>

只有两个对象:

> db.sa.find()
{ "_id" : ObjectId("50d636baa050939da1e4c53b"), "url" : "http://www.example.com", "crawled" : true }
{ "_id" : ObjectId("50d636dba050939da1e4c53d"), "url" : "http://www.example2.com/", "crawled" : false }

我已经用布尔值为true进行了测试,但问题仍然存在。 - guillaume
请更新您的问题并附上您当前的代码,它必须是一些微妙的东西。 - WiredPrairie
可能是吧,我刚刚添加了我的两个类。 - guillaume
你没有按照我的建议更改代码。选项,如unique,必须作为第二个参数(或第三个参数)传递:更多信息请参见ensureIndex。不要在键参数中使用.append。 - WiredPrairie
哎呀,我没看出区别。现在它可以工作了,谢谢 ;) - guillaume
ensureIndex已被弃用,推荐使用createIndex,如果索引不存在,则现在会创建一个索引。 - viking

2

我不完全明白你的问题,但我觉得你很可能应该使用ensureIndex而不是createIndex,因为后者总是试图创建索引,而前者只会确保它存在。


我尝试使用 collection.ensureIndex(new BasicDBObject("url", 1).append("unique", true));,但问题仍然存在。实际上,我的问题是我在URL上有一个唯一索引,但如果我多次插入相同的URL,则会产生多条记录而不仅仅是一条。 - guillaume

2

我刚偶然看到了这个问题,自从3.0.0版本以来有一些更改。

db.collection.ensureIndex(keys, options)

自3.0.0版本起已被弃用: db.collection.ensureIndex()现在是 db.collection.createIndex()的别名。

如果索引不存在,则在指定字段上创建索引。


0

另外我发现你在getCollection()中没有指定集合名称;

那会选择哪个集合呢?好奇


NM,我看到你使用了setCollection(),抱歉。 - med116

0
使用 MongoDB 的唯一索引,您应该使用具有 2 个参数的方法,其中第三个布尔参数用于 "unique" 索引。

mongo.getCollection().ensureIndex(new BasicDBObject("url", 1),"unq_url", true));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接