一. JAVA中设置MongoDB 复合索引
数据库tutorial中的集合student数据结构:
> db.student.find()
{ "_id" : ObjectId("51d24cd83c76712b265b05f3"), "classid" : 1, "age" : 23, "name" : "zhangsan" }
{ "_id" : ObjectId("51d24cd83c76712b265b05f4"), "classid" : 2, "age" : 26, "name" : "lisi" }
{ "_id" : ObjectId("51d24cd83c76712b265b05f5"), "classid" : 2, "age" : 8, "name" : "Bruce" }
{ "_id" : ObjectId("51d24cd83c76712b265b05f6"), "classid" : 2, "age" : 29, "name" : "Colin" }
用java驱动对mongoDB中的集合student创建复合索引:
DBCollection coll = db.getCollection("student");
DBObject index = new BasicDBObject();
// combine name&age as hybrid index
index.put("name", 1);
index.put("age", 1);
coll.createIndex(index);
List<DBObject> indexes = coll.getIndexInfo();
for (DBObject item : indexes){
System.out.println(item);
}
打印结果如下:
{ "v" : 1 , "key" : { "_id" : 1} , "ns" : "tutorial.student" , "name" : "_id_"}
{ "v" : 1 , "key" : { "name" : 1 , "age" : 1} , "ns" : "tutorial.student" , "name" : "name_1_age_1"}
person集合的数据结构:
> db.person.find()
{ "_id" : ObjectId("51d3904e9b0a7d476e95885e"), "address" : { "city" : "shenzhen", "state" : "SZ" }, "age" : 26, "username" : "zhangmin" }
{ "_id" : ObjectId("51d390599b0a7d476e95885f"), "address" : { "city" : "hangzhou", "state" : "ZJ" }, "age" : 25, "username" : "wuzixu" }
对其创建address.city和address.state的复合索引:
DBCollection coll = db.getCollection("person");
DBObject index = new BasicDBObject();
// combine address.city&address.state as hybrid index
index.put("address.city", 1);
index.put("address.state", 1);
coll.createIndex(index);
索引创建结果:
{ "v" : 1 , "key" : { "_id" : 1} , "ns" : "tutorial.person" , "name" : "_id_"}
{ "v" : 1 , "key" : { "address.city" : 1 , "address.state" : 1} , "ns" : "tutorial.person" , "name" : "address.city_1_address.state_1"}
?问题?:不知道怎么使用API,可以在创建索引的时候定义索引的名字,比如address_hybrid_index而不是默认的 address.city_1_address.state_1。
二. JAVA中自定义MongoDB索引名称
经过查看源代码,发现如果需要设置索引名称,必须调用包含com.mongodb.DBObject options 参数的createIndex方法,如:
public void createIndex(com.mongodb.DBObject keys, com.mongodb.DBObject options)
如上例,我们只有一个参数的createIndex,那么java driver的处理是:
public void createIndex( final DBObject keys ){
createIndex( keys , defaultOptions( keys ) );
}
其中keys 就是我们用的address.city 和address.state,由于我们没有设置options,那么java driver 就使用默认的实现方式:
DBObject defaultOptions( DBObject keys ){
DBObject o = new BasicDBObject();
o.put( "name" , genIndexName( keys ) );
o.put( "ns" , _fullName );
return o;
}
public static String genIndexName( DBObject keys ){
StringBuilder name = new StringBuilder();
for ( String s : keys.keySet() ){
if ( name.length() > 0 )
name.append( '_' );
name.append( s ).append( '_' );
Object val = keys.get( s );
if ( val instanceof Number || val instanceof String )
name.append( val.toString().replace( ' ', '_' ) );
}
return name.toString();
}
protected DBCollection( DB base , String name ){
_db = base;
_name = name;
_fullName = _db.getName() + "." + name;
_options = new Bytes.OptionHolder( _db._options );
}
可以看出,Index 的 name 就是通过getIndexName方法来的,最终形如:address.city_1_address.state_1。而 ns 的值是根据 _fullName 来的,_fullName的赋值是在DBCollection() 这个构造函数调用的时候就确定好了。这里:db.getCollection("person"); 所以,_fullName == "tutorial.person",tutorial是我的数据库名,而person是集合。
至此,我们了解了默认索引名称的形成,就可以通过设置来完成自定义索引名称,代码如下:
DBCollection coll = db.getCollection("person");
DBObject index = new BasicDBObject();
// 'name' is our desired name for index, but 'ns' must be set to make options work
DBObject options = new BasicDBObject();
options.put("name", "address_hybrid_index");
options.put("ns", coll.getFullName());
// combine address.city&address.state as hybrid index
index.put("address.city", 1);
index.put("address.state", 1);
coll.createIndex(index, options);
List<DBObject> indexes = coll.getIndexInfo();
for (DBObject item : indexes){
System.out.println(item);
}
直接看结果:
{ "v" : 1 , "key" : { "_id" : 1} , "ns" : "tutorial.person" , "name" : "_id_"}
{ "v" : 1 , "key" : { "address.city" : 1 , "address.state" : 1} , "ns" : "tutorial.person" , "name" : "address_hybrid_index"}