(转)Mongodb操作的一些方法,索引等

来源:互联网 发布:mac版千牛多账号登陆 编辑:程序博客网 时间:2024/05/29 18:11

本文转摘至:http://www.myexception.cn/database/922483.html



数据库、索引

2.1数据库

mongodb中的数据库对应文档,在前面已经介绍可以通过

DB db = mongo.getDB("sample");

来实例一个数据库对象,如果当然Mongo实例没有该数据库会默认创建一个。此外还提供了一些方法操作数据库:

//获取当前mongo实例创建后所有数据库,可能包括在客户端创建而服务端不存在的数据库(数据库开始在客户端不存在)public Collection<DB> getUsedDatabases();//返回服务端所有数据库名字public List<String> getDatabaseNames();//删除指定数据库public void dropDatabase(String dbName);

当然对于数据库,删除也可以通过DB对象方法:

//删除数据库DB db = mongo.getDB("sample");db.dropDatabase();
db.command(new BasicDBObject("dropDatabase", 1));

 

2.2索引

在mongo中,我们可以通过以下命令来建立索引:

//对username建立索引db.smaple.ensureIndex({"username":1})//对username建立正向索引,age简历反向索引db.smaple.ensureIndex({"username":1, "age":-1})//唯一索引db.smaple.ensureIndex({"username":1},{"unique":true})//消除重复索引db.smaple.ensureIndex({"username":1},{"unique":true,"dropDups":true})

在java中也可以通过以下api来做同样的事情:

//创建索引collection.createIndex(new BasicDBObject("username", 1));//指定索引名称collection.ensureIndex(new BasicDBObject("age", -1), "age_index");//创建唯一索引:如果数据重复将会报错//com.mongodb.MongoException$DuplicateKey: E11000 duplicate key error index: sample.user.$age_name_index  dup keycollection.ensureIndex(new BasicDBObject("age", -1).append("username", 1), "age_name_index", true);//根据索引名称删除collection.dropIndex("username_1");//删除索引索引collection.dropIndexes();

 

3、其他

1、索引与执行计划

现在表sample有10w数据内容如下:

{"username":"robin-i", "age":i,"info":{"title":"jee","salary":i}} 

根据条件查询

collection.find(new BasicDBObject("username", "robin-123")) 

这里通过对username建立索引来查看其执行计划:

//对username建立升序的索引collection.ensureIndex(new BasicDBObject("username", 1), "username_index"); 
//通过DbCursor的explain()来查看执行计划collection.find(new BasicDBObject("username", "robin-123")).explain()

下面是没有建索引和建立索引后两者的执行计划:

{ "cursor" : "BasicCursor" , "nscanned" : 100000 , "nscannedObjects" : 100000 , "n" : 1 , "millis" : 66 , "nYields" : 0 , "nChunkSkips" : 0 , "isMultiKey" : false , "indexOnly" : false , "indexBounds" : { } , "allPlans" : [ { "cursor" : "BasicCursor" , "indexBounds" : { }}] , "oldPlan" : { "cursor" : "BasicCursor" , "indexBounds" : { }}}
{ "cursor" : "BtreeCursor username_index" , "nscanned" : 1 , "nscannedObjects" : 1 , "n" : 1 , "millis" : 0 , "nYields" : 0 , "nChunkSkips" : 0 , "isMultiKey" : false , "indexOnly" : false , "indexBounds" : { "username" : [ [ "robin-123" , "robin-123"]]} , "allPlans" : [ { "cursor" : "BtreeCursor username_index" , "indexBounds" : { "username" : [ [ "robin-123" , "robin-123"]]}}]}

重点关注cursor、nscanned、n、millis等参数:

cursor: 这里出现的是”BasicCursor"和"BtreeCursor username_index"。就是说前者使用了表扫描,后者使用了索引nscanned: 前者没有索引扫描了10w条数据,而后者仅扫描了1条,结果已很明显n: 这里是1,也就是最终返回了1个文档。millis: 执行查询花费的时间,这是我们很关注的因素,前者耗时66ms,而有索引的0ms

 

2、聚合

在mongodb官网有介绍具体用法http://www.mongodb.org/display/DOCS/Aggregation这里主要介绍java中对聚合的一些支持,包括count、sort、distinct、group等,对高级的mapreduce并不涉及

2.1、count

//会立即返回该文档的记录数collection.count()//返回匹配的数量collection.count(DBObject query)

 

2.2、sort

sort是对结果集的操作,故DBCursor中

DBCursor cursor = collection.find().sort(new BasicDBObject("username", 1));

这个方法必须要在从DBCursor获取对象之前调用

 

2.3、distinct

对指定的字段去重复查询

{ "_id" : ObjectId("5098d9c782967d6792743d6c"), "name" : "Robin", "age" : 30 }{ "_id" : ObjectId("5098d9c782967d6792743d6d"), "name" : "Lisa", "age" : 28 }{ "_id" : ObjectId("5098d9c782967d6792743d6e"), "name" : "Amanda", "age" : 28 }{ "_id" : ObjectId("5098d9c782967d6792743d6f"), "name" : "Ace", "age" : 27 }{ "_id" : ObjectId("5098d9c782967d6792743d70"), "name" : "Joe", "age" : 30 }

 采用mongo的runCommand:

> db.runCommand({'distinct':'foo','key':'age'});{"values" : [30,28,27],"stats" : {"n" : 5,"nscanned" : 5,"nscannedObjects" : 5,"timems" : 0,"cursor" : "BasicCursor"},"ok" : 1}

 javaApi的支持:

List list = collection.distinct("age");返回[30,28,27]List list = collection.distinct("age", new BasicDBObject("name", "Robin"));返回[30]

 

2.4、group

还是上面的数据,我们根据age来分组,将name用","分割

String reduce = "function(cur, pre){pre.name += cur.name+' '}";GroupCommand command = new GroupCommand(collection, new BasicDBObject("age", true), null, new BasicDBObject("name", ""), reduce, null);DBObject dbObject = collection.group(command);
{ "age" : 30.0 , "name" : "Robin Joe "} , { "age" : 28.0 , "name" : "Lisa Amanda "} , { "age" : 27.0 , "name" : "Ace "}

还有几个多态的API,根据参数不同调用,都会用到上面的GroupCommand,这里结束GroupCommand中的几个属性的意思:

    public GroupCommand(DBCollection inputCollection, DBObject keys, DBObject condition, DBObject initial, String reduce, String finalize) {        this.input = inputCollection.getName();        this.keys = keys;        this.condition = condition;        this.initial = initial;        this.reduce = reduce;        this.finalize = finalize;    }
keys: 这个就是分组的key,这里是age。支持多个initial: 初始化参数,这里指定name其值为“”,当然如果我们涉及求和我们可以指定该初始值为0reduce: 这个函数的第一个参数是当前的文档对象,第二个参数是上一次function操作的累计对象
condition:指定过滤条件

 

2.3、命令

mongodb提供了许多命令对数据的管理或CURD操作。比如要查看数据库的状态,我们可以:

> db.runCommand({"dbStats":1}){"db" : "sample","collections" : 3,"objects" : 17,"avgObjSize" : 63.76470588235294,"dataSize" : 1084,"storageSize" : 11008,"numExtents" : 3,"indexes" : 1,"indexSize" : 8192,"fileSize" : 16777216,"ok" : 1}

可以通过在启动参数后加上

--rest 

查看命令http://localhost:28017/_commands 或者更多的命令见http://docs.mongodb.org/manual/reference/command/

当然java驱动也提供了相应的接口:

CommandResult command = db.command("dbStats");CommandResult res = command(new BasicDBObject("dropDatabase", 1));

另外还提供了一些列的方法可供使用,其实在javaApi中不难发现很多方法底层调用的这样的命令,如下面的删除索引的方法:

    public void dropIndexes( String name ){        DBObject cmd = BasicDBObjectBuilder.start()            .add( "deleteIndexes" , getName() )            .add( "index" , name )            .get();        resetIndexCache();        CommandResult res = _db.command( cmd );        if (res.ok() || res.getErrorMessage().equals( "ns not found" ))            return;        res.throwOnError();    }

这里罗列一些常见的命令,当然在javaApi中基本都有同名的方法:

//返回指定集合的统计信息{"collStats" : collection}//去从{"distinct" : collection, "key" : key, "query" : query}//删除集合数据{"drop" : collection}//删除当前数据库所有数据{"dropDatabase" : 1}
//删除集合里指定的索引{"dropIndexes" : collection, "index" : name}