转载:mongoDB java驱动学习笔记

http://www.blogjava.net/watchzerg/archive/2012/09/22/388346.html

mongoDB java驱动学习笔记


指定新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 ofmembers
Mongo m = new Mongo(Arrays.asList(newServerAddress("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 < i <= 30的记录:
query = new BasicDBObject();
query.put("i", new BasicDBObject("$gt",20).append("$lte", 30));  // i.e.  20 < i <= 30
cursor = coll.find(query);
try {
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
} finally {
cursor.close();
}
-------------------------------------------------------------
创建索引:
指定collection和要index的列即可,1代表升序,-1代表降序。
coll.createIndex(newBasicDBObject("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, firstwith the $match
DBObject match = newBasicDBObject("$match", new BasicDBObject("type", "airfare"));
// build the $projectionoperation
DBObject fields = newBasicDBObject("department", 1);
fields.put("amount", 1);
fields.put("_id", 0);
DBObject project = newBasicDBObject("$project", fields );
// Now the $group operation
DBObject groupFields = newBasicDBObject( "_id", "$department");
groupFields.put("average", newBasicDBObject( "$avg", "$amount"));
DBObject group = newBasicDBObject("$group", groupFields);
// run aggregation
AggregationOutput output =collection.aggregate( match, project, group );

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

public Iterable results()
public CommandResultgetCommandResult
public DBObjectgetCommand()

示例:
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连接,这时你可以通过使用"consistentrequest"来达到目的——在操作前后分别调用requestStart()和requestDone()。
DB db...;
db.requestStart();
try {
//Ensures that aconnection 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();
例如:假设我们的应用需要保持强一致性(写入的数据立即可以被读出),但是我们又希望万一主库挂掉以后,从库依然可以读取。这种情况下,我们需要选择PRIMARYPREFERRED模式:
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驱动可以确定自己的请求发送源位置,那么就可以明确指定将读请求发送到距离最近的数据中心。再看上面的例子,假如这个读请求来自南加利福尼亚,我们就明确指定这个读请求到LosAngeles数据中心:
// 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", "LosAngeles"):
DBObject tagSetTwo = new BasicDBObject("region","US_West");
ReadPreference pref =ReadPreference.primaryPreferred(tagSetOne, tagSetTwo);
下面的例子同样指定多个tag,首先请求"datacenter=LosAngeles"且"rack=1"的节点,如果失败则查找"region=US_West"的节点
// read from either LA or US_West
DBObject tagSetOne = new BasicDBObject("datacenter", "LosAngeles");
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+)都可以使用。
在优先读取策略(ReadPreferences)中使用节点标记(Tags)在所有支持节点标记的服务器(2.0+)都可以使用。
在分片(shard)上使用节点标记(Tags),必须是2.2+版本的服务器才可以。

转载于:https://www.cnblogs.com/leeeee/p/7276594.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1694. 重新格式化电话号码(模拟)

文章目录1. 题目2. 解题1. 题目 给你一个字符串形式的电话号码 number 。 number 由数字、空格 、和破折号 - 组成。 请你按下述方式重新格式化电话号码。 首先&#xff0c;删除 所有的空格和破折号。 其次&#xff0c;将数组从左到右 每 3 个一组 分块&#xff0c;直到 剩…

Python中查找包含它的列表元素的索引,index报错!!!

对于列表["foo", "bar", "baz"]和列表中的项目"bar"&#xff0c;如何在Python中获取其索引&#xff08;1&#xff09;&#xff1f; 一、index >>> ["foo", "bar", "baz"].index("bar&qu…

LeetCode 1695. 删除子数组的最大得分(前缀和+哈希+双指针)

文章目录1. 题目2. 解题1. 题目 给你一个正整数数组 nums &#xff0c;请你从中删除一个含有 若干不同元素 的子数组。 删除子数组的 得分 就是子数组各元素之 和 。 返回 只删除一个 子数组可获得的 最大得分 。 如果数组 b 是数组 a 的一个连续子序列&#xff0c;即如果它…

大型网站系统与Java中间件实践

大型网站系统与Java中间件实践&#xff08;贯通分布式高并发高数据高访问量网站架构与实现之权威著作&#xff0c;九大一线互联网公司CTO联合推荐&#xff09; 曾宪杰 著 ISBN 978-7-121-22761-5 2014年4月出版 定价&#xff1a;65.00元 340页 16开 编辑推荐 到底是本什么书…

2019年CSDN人气最高博客排名榜(前20强),业界传说,膜拜!

截止到2019年02月12日&#xff0c;CSDN前二十的大神&#xff1a; 1. stpeace&#xff1a;原创2150&#xff0c;粉丝5037&#xff0c;评论2966&#xff0c;访问量1613万 链接&#xff1a;https://blog.csdn.net/stpeace/ 简介&#xff1a;近几年排名稳步上升&#xff0c;至今仍…

LeetCode 1696. 跳跃游戏 VI(优先队列 / 单调队列)

文章目录1. 题目2. 解题2.1 贪心错误解2.2 优先队列/单调队列1. 题目 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 一开始你在下标 0 处。每一步&#xff0c;你最多可以往前跳 k 步&#xff0c;但你不能跳出数组的边界。 也就是说&#xff0c;你可以从下标 i 跳到…

Unable to open /dev/sda的原因之一

fdsik /dev/sda需要在root权限下运行&#xff0c;普通用户就会出现上述情况。 转载于:https://www.cnblogs.com/cnsec/p/3789828.html

Python判断变量是否存在的方法

方法一&#xff1a;使用try: ... except NameError: ...。 try:var except NameError:var_exists False else:var_exists True 方法二&#xff1a;使用内置函数locals()&#xff1a; locals()&#xff1a;获取已定义对象字典 #testvar未定义 In [1]: testvar in locals().…

LeetCode 1697. 检查边长度限制的路径是否存在(排序+并查集)

文章目录1. 题目2. 解题1. 题目 给你一个 n 个点组成的无向图边集 edgeList &#xff0c;其中 edgeList[i] [ui, vi, disi] 表示点 ui 和点 vi 之间有一条长度为 disi 的边。请注意&#xff0c;两个点之间可能有 超过一条边 。 给你一个查询数组queries &#xff0c;其中 qu…

限制RICHTEXTBOX的输入的范围

附件&#xff1a;http://files.cnblogs.com/xe2011/WindowsFormsApplication_LimitRichTextBoxInput.rarusing System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using Syst…

NLP项目工作流程

文章目录1. 谷歌Colab设置2. 编写代码3. flask 微服务4. 打包到容器5. 容器托管参考 基于深度学习的自然语言处理使用这篇文章的数据(情感分类)进行学习。 1. 谷歌Colab设置 Colab 地址 新建笔记本 设置 选择 GPU/TPU 加速计算 测试 GPU 是否分配 import tensorflow…

判断 Python 对象是否包含某个属性的方法

先创建两个类&#xff0c;判断类的属性是否存在&#xff1a; class Foo(object):def __init__(self):super(Foo, self).__init__()self.is_whole 1class Doo(object):def __init__(self):super(Doo, self).__init__()f Foo() d Doo() 方法一&#xff1a;通过异常捕捉来实…

牛客 牛牛浇树(差分)

文章目录1. 题目2. 解题1. 题目 链接&#xff1a;https://ac.nowcoder.com/acm/contest/10323/A 来源&#xff1a;牛客网 牛牛现在在花园养了n棵树&#xff0c;按顺序从第1棵到第n棵排列着。 牛牛每天会按照心情给其中某一个区间的树浇水。 例如如果某一天浇水的区间为[2,4]&…

再议 语法高亮插件的选择

之前一篇《为博客园选择一个小巧霸气的语法高亮插件》介绍了语法高亮插件的选择&#xff0c;当时只注重速度了。这些天在做深度定制的时候发现一个严重的问题&#xff0c;匹配精度不够。 什么是匹配精度呢&#xff1f;简单说就是没有把代码分块&#xff0c;是否分的足够细&…

Python自定义时间间隔访问网页

方法一&#xff1a;利用webbrowser import time import webbrowserwhile True: # 死循环time.sleep(60 * 1) # 程序等待时间&#xff0c;这里等待1min&#xff0c;参数的基本单位是秒print("正在访问&#xff1a;请稍等。。。")webbrowser.open("https://blo…

Arch Linux下打不开gnome-shell

可能与未正确设置语言环境有关。 检查语言设置&#xff1a;locale -a 检查当前环境下设置&#xff1a;echo $LANG 检查/etc/locale.conf是否存在&#xff0c;是否正确设置。如果不存在&#xff1a;echo en_US.UTF-8 > /etc/locale.conf转载于:https://www.cnblogs.com/vanit…

牛客 挑选方案问题(排列组合)

文章目录1. 题目2. 解题1. 题目 链接&#xff1a;https://ac.nowcoder.com/acm/contest/10323/B 来源&#xff1a;牛客网 自助餐厅里有5个盘子&#xff0c;里面装的都是面包。 第1个盘子里有无限个面包&#xff1b; 第2个盘子里只有1个面包&#xff1b; 第3个盘子里只有4个面…

微信定时每天给女友发送甜言蜜语(附代码教程)

准备工作&#xff1a; 微信&#xff08;扫码登陆网页版&#xff09;pip install wxpypip install requests 代码教程&#xff1a; from __future__ import unicode_literals from threading import Timer from wxpy import * import requests import randombot Bot()# linu…

【Github教程】史上最全github用法:github入门到精通

原文 http://www.eoeandroid.com/thread-274556-1-1.html 【初识Github】 首先让我们大家一起喊一句“Hello Github”。YEAH!就是这样。Git是一个分布式的版本号控制系统&#xff0c;最初由Linus Torvalds编写&#xff0c;用作Linux内核代码的管理。在推出后&#xff0c;Git在其…

牛客 统计好元组

文章目录1. 题目2. 解题1. 题目 链接&#xff1a;https://ac.nowcoder.com/acm/contest/10325/A 来源&#xff1a;牛客网 现在给定一个数组arr&#xff0c;和a,b两个数字&#xff0c;你要做的就是找到&#xff08;i&#xff0c;j&#xff0c;k&#xff09;。且满足 1. 0 <…