热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何使用MongoDB数据库的Java驱动

指定新mongo实例:MongomnewMongo();MongomnewMongo(localhost);MongomnewMongo(localhost,27017);//or,toconnecttoareplicaset,supplyaseedlistofmembersMongomnewMongo(Arrays.

指定新mongo实例:

Mongo m = new Mongo();

Mongo m = new Mongo( "localhost" );

Mongo m = new Mongo( "localhost" , 27017 );

// or, to connect to a replica set, supply a seed list of members

Mongo m = new Mongo(Arrays.asList(new ServerAddress("localhost", 27017),

                    new ServerAddress("localhost", 27018),

                    new ServerAddress("localhost", 27019)));

然后发起连接(必须指定数据库名,可以不存在)

DB db = m.getDB( "mydb" );

注意Mongo已经实现了连接池,并且是线程安全的。

大部分用户使用mongodb都在安全内网下,但如果将mongodb设为安全验证模式,就需要在客户端提供用户名和密码:

boolean auth = db.authenticate(myUserName, myPassword);

获取集合(collection)的名称列表(类似show databases):

Set colls = db.getCollectionNames();

获取一个集合(以便增删改查操作):

DBCollection coll = db.getCollection("testCollection")

-------------------------------------------------------------

先假设要插入的json数据如下:

{

   "name" : "MongoDB",

   "type" : "database",

   "count" : 1,

   "info" : {

               x : 203,

               y : 102

             }

}

将其插入数据库:

        BasicDBObject doc = new BasicDBObject();

        doc.put("name", "MongoDB");

        doc.put("type", "database");

        doc.put("count", 1);

        BasicDBObject info = new BasicDBObject();

        info.put("x", 203);

        info.put("y", 102);

        doc.put("info", info);

        coll.insert(doc);

-------------------------------------------------------------

设定write concern,以便操作失败时得到提示:

m.setWriteConcern(WriteConcern.SAFE);

-------------------------------------------------------------

查找一个/第一个记录:

DBObject myDoc = coll.findOne();

System.out.println(myDoc);

注意:属性名不能以下划线或者美元符号开始,mongodb自己保留。

获取总记录数:

System.out.println(coll.getCount());

使用游标操作查询结果:

        DBCursor cursor = coll.find();

        try {

            while(cursor.hasNext()) {

                System.out.println(cursor.next());

            }

        } finally {

            cursor.close();

        }

条件查询:

        BasicDBObject query = new BasicDBObject();

        query.put("i", 71);

        cursor = coll.find(query);

        try {

            while(cursor.hasNext()) {

                System.out.println(cursor.next());

            }

        } finally {

            cursor.close();

        }

如果想使用shell里的类似以下语句的功能:

db.things.find({j: {$ne: 3}, k: {$gt: 10} });

在java驱动里,{$ne: 3}也是一个普通的DBObject:

        BasicDBObject query = new BasicDBObject();

        query.put("j", new BasicDBObject("$ne", 3));

        query.put("k", new BasicDBObject("$gt", 10));

        cursor = coll.find(query);

        try {

            while(cursor.hasNext()) {

                System.out.println(cursor.next());

            }

        } finally {

            cursor.close();

        }

条件查询一批数据:

以下是查询i > 50的记录:

        query = new BasicDBObject();

        query.put("i", new BasicDBObject("$gt", 50));  // e.g. find all where i > 50

        cursor = coll.find(query);

        try {

            while(cursor.hasNext()) {

                System.out.println(cursor.next());

            }

        } finally {

            cursor.close();

        }         

以下是查询20

        query = new BasicDBObject();

        query.put("i", new BasicDBObject("$gt", 20).append("$lte", 30));  // i.e.   20

        cursor = coll.find(query);

        try {

            while(cursor.hasNext()) {

                System.out.println(cursor.next());

            }

        } finally {

            cursor.close();

        }

-------------------------------------------------------------

创建索引:

指定collection和要index的列即可,1代表升序,-1代表降序。

coll.createIndex(new BasicDBObject("i", 1));  // create index on "i", ascending

获取索引列表:

List list = coll.getIndexInfo();

          for (DBObject o : list) {

            System.out.println(o);

        }

-------------------------------------------------------------

数据库管理相关的命令:

获取数据库名称列表:

m.getDatabaseNames()

删除数据库:

m.dropDatabase("my_new_db");

-------------------------------------------------------------

聚合函数:使用DBCollection.aggregate()产生聚合任务:

http://www.mongodb.org/display/DOCS/Using+The+Aggregation+Framework+with+The+Java+Driver

// create our pipeline operations, first with the $match

DBObject match = new BasicDBObject("$match", new BasicDBObject("type", "airfare") );

// build the $projection operation

DBObject fields = new BasicDBObject("department", 1);

fields.put("amount", 1);

fields.put("_id", 0);

DBObject project = new BasicDBObject("$project", fields );

// Now the $group operation

DBObject groupFields = new BasicDBObject( "_id", "$department");

groupFields.put("average", new BasicDBObject( "$avg", "$amount"));

DBObject group = new BasicDBObject("$group", groupFields);

// run aggregation

AggregationOutput output = collection.aggregate( match, project, group );

返回结果是一个AggregationOutput对象,可以用以下方式获取其中信息:

public Iterable results()

public CommandResult getCommandResult

public DBObject getCommand()

示例:

System.out.println(output.getCommandResult());

{

"serverUsed" : "/127.0.0.1:27017" ,

"result" : [

{"_id" : "Human Resources" , "average" : 74.91735537190083} ,

{"_id" : "Sales" , "average" : 72.30275229357798} ,

{"_id" : "Engineering" , "average" : 74.1}

] ,

"ok" : 1.0

}

-------------------------------------------------------------

使用DBObject存取对象:

http://www.mongodb.org/display/DOCS/Java+-+Saving+Objects+Using+DBObject

假设一个类叫做twitter,存储前必须实现DBObject接口:

public class Tweet implements DBObject {

    /* ... */

}

然后就可以存了:

Tweet myTweet = new Tweet();

myTweet.put("user", userId);

myTweet.put("message", msg);

myTweet.put("date", new Date());

collection.insert(myTweet);

一个文档从数据库取出时,自动被转为DBObject。如果想取出时转为需要的类,可以先调用DBCollection.setObjectClass(),然后再进行类型强制转换:

collection.setObjectClass(Tweet.class);

Tweet myTweet = (Tweet)collection.findOne();

如果想要改变Tweet类的属性,可以改完后再存入:

Tweet myTweet = (Tweet)collection.findOne();

myTweet.put("message", newMsg);

collection.save(myTweet);

-------------------------------------------------------------

JAVA驱动的并发:

http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency

mongodb的java驱动是线程安全的,如果是在web服务环境下,应该创建单例的mongo对象,用这个对象处理每一个请求。mongo对象维护一个内部连接池(默认大小为10),对于每个请求(查找插入等),java线程会从线程池取一个连接,执行操作,然后释放连接——这意味着每次操作所使用的连接很有可能是不同的。

------------------------------

在复制(replica)模式下,如果设置slaveOK选项为on,那么读操作会被均匀的分布到各个slave上。这意味着对于同一个线程,一个写操作后紧跟着的一个读操作,有可能被发送到不同的服务器上(写操作发送到master上,读操作发送到slave上),这样读操作有可能不会立刻反映出上一个写操作的数据(因为主从的异步性)。

如果你想要确保在一个session中完整的一致性(例如在一个http请求中),你可能希望java驱动是用同一个socket连接,这时你可以通过使用"consistent request"来达到目的——在操作前后分别调用requestStart()和requestDone()。

DB db...;

db.requestStart();

try {

   //Ensures that a connection exists for the "consistent request"

   db.requestEnsureConnection();

   code....

} finally {

   db.requestDone();

}

------------------------------

在单独写操作上的WriteConcern选项:

默认情况下,每次写操作后,连接就被释放回连接池——此时你调用getLastError()是没用的。

所以可以采用两种方式:

1,使用类似WriteConcern.SAFE这样的写策略来代替默认策略,这样java驱动会自动首先调用getLastError(),然后才将连接放回连接池。

DBCollection coll...;

coll.insert(..., WriteConcern.SAFE);

2,采用上述的requestStart()和requestDone()方式来维持连接不被释放,中间调用getLastError()获取错误信息。

DB db...;

DBCollection coll...;

db.requestStart();

try {

   coll.insert(...);

   DBObject err = db.getLastError();

} finally {

   db.requestDone();

}

这两种方式等价。

-------------------------------------------------------------

java类型:

http://www.mongodb.org/display/DOCS/Java+Types

----------------------------

Object id被用来自动生成唯一的ID:

ObjectId id = new ObjectId();

ObjectId copy = new ObjectId(id);

----------------------------

正则表达式:

java驱动使用JDK的java.util.regex.Pattern表达正则:

Pattern john = Pattern.compile("joh?n", CASE_INSENSITIVE);

BasicDBObject query = new BasicDBObject("name", john);

// finds all people with "name" matching /joh?n/i

DBCursor cursor = collection.find(query);

----------------------------

java驱动使用JDK的 java.util.Date表示日期时间:

Date now = new Date();

BasicDBObject time = new BasicDBObject("ts", now);

collection.save(time);

----------------------------

com.mongodb.DBRef被用来表示数据库引用(官方一般建议手动引用):

DBRef addressRef = new DBRef(db, "foo.bar", address_id);

DBObject address = addressRef.fetch();

DBObject person = BasicDBObjectBuilder.start()

    .add("name", "Fred")

    .add("address", addressRef)

    .get();

collection.save(person);

DBObject fred = collection.findOne();

DBRef addressObj = (DBRef)fred.get("address");

addressObj.fetch()

----------------------------

二进制数据:

java中的字节数组会自动被包装成二进制数据存入数据库。

二进制类可以被用来表示二进制对象,这可以用来取一个自定义类型的字节。

----------------------------

时间戳数据(BSONTimestamp对象):

时间戳数据是一个mongoDB使用的特殊对象,表示一个(以秒为单位的时间,自增ID)的键值对,这被用于主从复制的操作日志中。

----------------------------

代码对象:

用于表示Javascript代码,例如保存可执行的方法到system.js集合中。

Code和CodeWScope类用来表示这种数据。

注意有些方法(比如map/reduce)接收字符串,但是在驱动中将其包装为代码对象。

----------------------------

嵌套对象:

在Javascript里面这样一个json文档:

{

    "x" : {

        "y" : 3

    }

}

在java中对应的形式是:

BasicDBObject y = new BasicDBObject("y", 3);

BasicDBObject x = new BasicDBObject("x", y);

----------------------------

数组:

java中所有实现List接口的都被以数组形式在数据库中保存:

所以如果想保存这样一个json:

{

    "x" : [

        1,

        2,

        {"foo" : "bar"},

        4

    ]

}

在java中可以这么做:

ArrayList x = new ArrayList();

x.add(1);

x.add(2);

x.add(new BasicDBObject("foo", "bar"));

x.add(4);

BasicDBObject doc = new BasicDBObject("x", x);

-------------------------------------------------------------

在java驱动中的优先读取策略(Read Preferences)和节点标记(Tagging)

http://www.mongodb.org/display/DOCS/Read+Preferences+and+Tagging+in+The+Java+Driver

用来允许应用程序开发者能将读写操作指定在某个主从集合的成员节点上。

2.2版本在节点标记(node tagging)带来些新的东西让你能更好的控制你的数据的读写。

java驱动的2.9.0集成了mongodb2.2提供的所有新特性。

----------------------------

优先读取策略(Read Preferences):

用于提供客户端程序选择那个节点来读取,有以下五个选择:

PRIMARY : 默认方式,从主节点读取,如果主节点不可用则抛出异常,无法与标签(tags)一起使用。

PRIMARY PREFERRED : 优先读取主节点,失败的话从副节点读取。

SECONDARY : 从副节点读取,失败则抛异常。

SECONDARY PREFERRED : 优先读取副节点,失败则从主节点读取。

NEAREST : 从最近的节点读取,“最近”的定义为ping的响应时间最短(也得满足15毫秒以内)。

java实现:类ReadPreference的工厂模式可以创建对应上述五种策略的对象:

ReadPreference.primary();

ReadPreference.primaryPreferred();

ReadPreference.secondary();

ReadPreference.secondaryPreferred();

ReadPreference.nearest();

例如:假设我们的应用需要保持强一致性(写入的数据立即可以被读出),但是我们又希望万一主库挂掉以后,从库依然可以读取。这种情况下,我们需要选择PRIMARY PREFERRED模式:

ReadPreference preference = ReadPreference.primaryPreferred();

DBCursor cur = new DBCursor(collection, query, null, preference);

java驱动保持着各个节点的状态信息(每隔一段时间ping一次所有节点),在这个例子中,java驱动会检测到主库的挂掉,从而将读操作指向从节点。

----------------------------

节点标记(Tags):

在mongoDB2.0之后,主从集群中的每一个节点都可以被标记一个描述,称为tags。可以用来标记一个节点的位置,和在集群中的从属关系或者特性。这可以让你的应用程序从指定节点中读写。

例子:

假设我们要运行一个三节点的主从集群,三个节点分别在三个不同地理位置的数据中心当中。我们希望确保我们的数据在灾难中也可以恢复,所以我们对每一个节点标记其地理位置,配置文件样例如下:

foo:SECONDARY> rs.conf()

{

    "_id":"foo",

    "version":103132,

     "members":[

         {

              "_id":0,

               "host":"localhost:27017",

               "priority":10,

               "tags":{

                   "datacenter":"Los Angeles",

                    "region":"US_West"

               }

          },

          {

              "_id":1,

               "host":"localhost:27018",

               "tags":{

                   "datacenter":"San Jose",

                    "region":"US_West"

               }

          },

          {

              "_id":2,

               "host":"localhost:27019",

               "tags":{

                   "datacenter":"Richmond",

                    "region":"US_Eest"

               }

          }

     ],

     "settings":{

         "getLastErrorModes":{

              "DRSafe":{

                   "region":2

               }

          }

     }

}

foo:SECONDARY>

注意上面settings字段,我们定义了一个新的getLastErrorModes对象,键为DRSafe。当我们客户端采用此错误模式作为WriteConcern的时候,它会使写操作在完成前复制到至少两个节点上。下面是使用的例子:

//使用自定义的getLastErrorMode创建WriteConcern

WriteConcern cOncern= new WriteConcern("DRSafe");

//使用自定义的WriteConcern进行写操作

coll.insert(new BasicDBObject("name", "simple doc"), concern);

----------------------------

在优先读取策略(Read Preferences)中使用节点标记(Tags):

假如我们想要将读请求发送到最近的节点上以便减少请求延时:

DBObject query = new BasicDBObject("name", "simple doc")

DBObject result = coll.findOne(query, null, ReadPreference.nearest());

这样java驱动会自动将读请求发送到ping值最小的节点(也有可能是主节点)。

但是,如果我们的java驱动可以确定自己的请求发送源位置,那么就可以明确指定将读请求发送到距离最近的数据中心。再看上面的例子,假如这个读请求来自南加利福尼亚,我们就明确指定这个读请求到Los Angeles数据中心:
// initialize a properly tagged read preference
ReadPreference tagged_pref = ReadPreference.secondaryPreferred(new BasicDBObject("datacenter", "Los Angeles"));
// include the tagged read preference in this request}}
DBObject result = coll.findOne(}}
new BasicDBObject("name", "simple doc"), null, tagged_pref);
下面的例子指定多个tag,如果读请求在Los Angeles失败,则发送到"US_West"区域的某个节点:
// read from either LA or US_West
DBObject tagSetOne= new BasicDBObject("datacenter", "Los Angeles"):
DBObject tagSetTwo = new BasicDBObject("region", "US_West");
ReadPreference pref = ReadPreference.primaryPreferred(tagSetOne, tagSetTwo);
下面的例子同样指定多个tag,首先请求"datacenter=Los Angeles"且"rack=1"的节点,如果失败则查找"region=US_West"的节点
// read from either LA or US_West
DBObject tagSetOne= new BasicDBObject("datacenter", "Los Angeles");
tagSetOne.put("rack", "1");
DBObject tagSetTwo = new BasicDBObject("region", "US_West");
ReadPreference pref = ReadPreference.primaryPreferred(tagSetOne, tagSetTwo);
优先读取策略(Read Preferences)可以在operation, collection, DB, Mongo, MongoOptions, MongoURI各个级别来设置,而且设置会以slaveOK和WriteConcer类似的方式来继承。
优先读取策略(Read Preferences)在支持主从复制的服务器上(1.6+)都可以使用。
在优先读取策略(Read Preferences)中使用节点标记(Tags)在所有支持节点标记的服务器(2.0+)都可以使用。
在分片(shard)上使用节点标记(Tags),必须是2.2+版本的服务器才可以。


推荐阅读
  • 58同城的Elasticsearch应用与平台构建实践
    本文由58同城高级架构师于伯伟分享,由陈树昌编辑整理,内容源自DataFunTalk。文章探讨了Elasticsearch作为分布式搜索和分析引擎的应用,特别是在58同城的实施案例,包括集群优化、典型应用实例及自动化平台建设等方面。 ... [详细]
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 解决MongoDB Compass远程连接问题
    本文记录了在使用阿里云服务器部署MongoDB后,通过MongoDB Compass进行远程连接时遇到的问题及解决方案。详细介绍了从防火墙配置到安全组设置的各个步骤,帮助读者顺利解决问题。 ... [详细]
  • 最近团队在部署DLP,作为一个技术人员对于黑盒看不到的地方还是充满了好奇心。多次咨询乙方人员DLP的算法原理是什么,他们都以商业秘密为由避而不谈,不得已只能自己查资料学习,于是有了下面的浅见。身为甲方,虽然不需要开发DLP产品,但是也有必要弄明白DLP基本的原理。俗话说工欲善其事必先利其器,只有在懂这个工具的原理之后才能更加灵活地使用这个工具,即使出现意外情况也能快速排错,越接近底层,越接近真相。根据DLP的实际用途,本文将DLP检测分为2部分,泄露关键字检测和近似重复文档检测。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
  • MongoDB的核心特性与架构解析
    本文深入探讨了MongoDB的核心特性,包括其强大的查询语言、灵活的文档模型以及高效的索引机制。此外,还详细介绍了MongoDB的体系结构,解释了其文档、集合和数据库的层次关系,并对比了MongoDB与传统关系型数据库(如MySQL)的逻辑结构。 ... [详细]
  • Spring Cloud因其强大的功能和灵活性,被誉为开发分布式系统的‘一站式’解决方案。它不仅简化了分布式系统中的常见模式实现,还被广泛应用于企业级生产环境中。本书内容详实,覆盖了从微服务基础到Spring Cloud的高级应用,适合各层次的开发者。 ... [详细]
  • 利用 Jest 和 Supertest 实现接口测试的全面指南
    本文深入探讨了如何使用 Jest 和 Supertest 进行接口测试,通过实际案例详细解析了测试环境的搭建、测试用例的编写以及异步测试的处理方法。 ... [详细]
  • This guide provides a comprehensive step-by-step approach to successfully installing the MongoDB PHP driver on XAMPP for macOS, ensuring a smooth and efficient setup process. ... [详细]
  • 探讨如何高效使用FastJSON进行JSON数据解析,特别是从复杂嵌套结构中提取特定字段值的方法。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
author-avatar
三封封封_391
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有