Mongodb——文档数据库
mongodb是一个文档数据库。
mongo操作
多个修改操作,但每个修改携带的数据包较小,可操作考虑批量操作.bulkWrite()
改善性能。
MongoCollection是线程安全的。
db.coll.find()(shell、java api)之后接.limit .skip .sort不论编码调用顺序如何,执行时都是.sort -> .skip -> .limit。
如果要定义limit, sort, skip的顺序,应该使用.aggregate管道流。
db.createCollection()在coll已存在情况下会出错(java api则抛异常),db.getCollection后接CRUD则会自动创建coll,仅仅db.getCollection(String)数据库不会自动创建。
skip()
不是O(1)时间,是O(n)时间,不建议使用。
cursor
batchSize:
insert
insertOne()若在唯一索引字段上有重复值时插入抛出异常。
query
查询一个字段的值
mongo-shell: find({},{'field':1,'_id':0}),指定返回字段field,_id字段默认返回,若不需要该字段故需显式关闭。
不等于查询$ne
:find({field:{$ne: val}})
区间查询 $gt
, $gte
, $lt
, $lte
db.collection.find({"myNum":{$gt:5, $lt:20}})
查询数组中满足条件的元素且只返回匹配的元素:
$elemMatch
匹配元素、"<数组字段名>.$
"返回仅匹配的元素
.find({'myArray': {$elemMatch: {$gt: 50}}}) //查询数组中元素大于50的元素
.projection({'myArray.$': 1}) //仅返回数组中匹配上的元素
查询文档数组字段中满足条件的最后一个元素:
mongo-shell pretty output(beautiful output) 配置
查询数组字段非空的文档:
有以下数种方式,假设目标字段名为"array"。
$elemMatch
和$ne
:
db.Collection.find({array:{$elemMatch:{$ne:null}}})
$where
+js数组的.length
db.Collection.find({$where:"this.array.length>0"})
$not
和$size
db.Collection.find({array: {$not: {$size: 0}}})
$exists
和'.
'路径试图访问首元素
db.Collection.find({{'array.0': {$exists: 1}}})
$exists
和$ne
db.Collection.find({ array: { $exists: true, $ne: [] } })
$gt
db.Collection.find({ array: { $gt: [] } })
TODO
查询object类型字段的键数量:
匹配object类型字段非空:
update
db.coll.updateOne(filter, update[, options])
db.coll.updateMany(filter, update[, options])
db.coll.replaceOne(filter, update, options)
update时不能在同一字段上有多个operator。即不允许这样的update:
.update({},{$pull:{"entity":'a'}, $addToSet:{entities:'b'}})
.updateOne查找一个数组字段中某个元素更新时,参数提供 {\(set:{'arrayField.\)':newValue},将会替换原来的值,需注意的是,当元素是json时(提供的newValue新值也是json),操作会直接替换掉原来的json,不是在原文档上添加字段或修改字段值。
涉及数组字段中更新查询到的元素时,在提供了占位符'$'的更新时,不存在upsert:true,因为在
更新/删除字段:
findAndUpdate(query, {"\(set", {field1:'val1'...}, "\)unset": {"fieldx":"值无所谓"}})
尽管insert方法没返回值,但驱动会自动生成_id(如果没有提供),并put到被插入的Document中。_id会根据时间戳、主机等信息生成。
upsert(search, doc) -> update or insert,这里的search相当于where条件,这比在客户端先search是否存在,然后决定insert还是update高效。
键名(key)可以是任意Unicode字符,但不允许包含点号.和美元符$,可以通过转义的方式存,常见的转义方式是将这两个ascii字符转到Unicode:. -> '\u2024':[․],\uff0e':[.], $ -> '\ufe69':[﹩],'\uff04':[$]。
db.collection.distinct("field") <- select distinct field
update operators:
**\(pull**
{\)pull: { : <value | condition> } } 从array字段删除符合条件的元素。
**\(pullAll**
{\)pullAll: { : [ value1, val2, ...] }}
从array字段删除操作中提供的多个元素(不是匹配条件),值为数组,不能是单值。
**\(push**
插入(结合\)position)或追加(无\(position)元素到数组字段,如果追加多个元素(一次性插入多个)需结合\)each。
{\(push: {<field>:<value>}} {\)push: {field: {$each: [,] } }}}
**\(addToSet**
{\)addToSet:{: },如果参数值是数组,则会被视为单一元素插入到目标字段(成为内嵌数组);如果想对一组元素都进行\(addToSet操作,应将这组元素封装到\)each操作:
{
$addToSet: {
"field":{$each:['v1','v2'...]}
}
}
$set
$setOnInsert
set when insert in upsert mode
delete/remove doc
.deleteOne(filter)
.deleteMany(filter)
aggregate
.aggregate([pipe1, pipe2])
$match, $project
count object keys: 利用\(objectToArray将对象转为数组,然后利用\)size。
.aggregate({\(project: {out: {\)size: {\(objectToArray: "\)valueeOfSomeKey"}}}})
数组上的aggregate: \(size(aggregate)
例:获取值类型为数组的字段"entities"上数组的长度 .aggregate({\)project:{ asNewFieldName: {\(size: "\)entities"}}),注意,引用字段entities时需要字段名前加\(,否则被认为是string常量,导致\)size操作失败。
update: { "\(update-opterator": {}, "\)update-operator":{} }
对于.updateOne(filter, update, opts),当filter是eq(全匹配)且upsert为true时,如果update的文档不存在,则在插入时会自动把filter上的字段-值插入。例: getCollection.updateOne(Filters.eq("nerword", "xxxxxx"), new bson.Document("$addToSet", new bson.Document("entities", "zzz")),new UpdateOptions().upsert(true)),如果不存在该nerword的文档,则插入时会加入nerword,即有新文档{nerword:'xxxxxx', entities:['zzz']}。对于replaceOne
with upsert: ture 在插入时不会添加filter的字段。
update
和replace
在filter指定的文档不存在且upsert:false时无任何操作。
update operator:
\(rename
\)set
$unset
backup/restore export(dump)/import
导出远程数据库集合
mongoexport -h <host> --port <port> -u <user> -p <pass> -d <db> -c <collection> -o <outputfile.json>
mongoimport -h .. --port .. -u .. -p .. -d .. -c .. --file <data.json>
# import csv
mongoimport -d <db> -c <coll> --type csv --headerline (first line is headerline, as fields) --ignoreBlanks (ignore blank values) --file <FILE>
数据库database
show dbs # 列举db
use <db> # 切换到db,如果不存在则在需要时创建
db # show current db
#use之后内置变量db指向当前的database。
use <db> # create <db>
db.dropDatabase() # drop database
用户user
db.getUsers()
db.createUser(
{
user:'name'
pwd:'password'
roles:[{role:'what-role',db:'which-db'}]
})
db role
show roels
// create role
// drop role
//增加授权,不会先清除之前的授权
db.grantRolesToUser('username',[
{role:'role1',db:'db1'}, {role:'role2',db:'db2'}])
// 收回授权
db.revokeRolesFromUser('username',[{role:'role1',db:'db1'},{role:'role2',db:'db2'}])
index 索引
db.coll.createIndex(keys, options)
//如果不存在则创建
db.collection.createIndex(
{<field>: 1/-1, <anotherField>: 1/-1},
<optional>{unique: true, name:"name for index", sparse: true|false}
)
字段有重复时创建唯一索引(unique index)会失败,{unique:true, dropDups:true}在 MOngoDB 3.0后不可取,dropDups选项无效。
数据状态异常
查询集合中文档数量 db..count()(包括.stats())的结果和通过find()结果遍历次数不一致,这是因为mongodb关于此集合的数据状态有异常,需要执行db..invalidate(true)来矫正数据,参考mongodb问题 count() incorrect。数据有误时可考虑用db..count({_id:{$exists:true}})代替count()。
mongo java driver
结论一般针对3.4.2版本
类型为Array[?]的字段值不能被解码,要为Collection[?]才行。例如,String[] x,则new Document("key",x)时,x存储会识别,因无法找到[Ljava.lang.String的codec,而存储转为List的x(x.asList)则能成功。
insertMany之前先判断插入的集合是否为空,因为插入空集合会引发异常(╮(╯▽╰)╭)
mongo-java-drive 3+
collection.updateOne(Filter.eq("id-or-other-field","xxxxxx"), new Document("$set", Document.parse(json: {timstamps: new Date, xx:{...})
updateOne vs. findOneAndUpdate 后者会返回更新前的值,前者不会。
插入整数时一定注意区分是int还是long型,分别与mongodb的Int32、Int64对应,如果是后者,用java api Document.getInteger会出异常,而往往直接用该方法取整数型数据。
无需auth信息的serve不能new 带credential的MongoClient构造器(MongoClient(ServerAddress, List[MongoCredential])。
【添加codec】
MongoClientOptions.builder().codecRegistry(CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new LocalDateTimeCodec()), MongoClient.getDefaultCodecRegistry()))
new Document(Map<String,Object>)(如从一个json构建)并不会将深层Map<String,Object>转为Document,因此使得插入时转码失败(code错误)。从json到document的一种正确方式是Document.parse(String json)。
mongodb python driver
package dependency: pymongo
from pymongo import MongoClient
cursor = MongoClient(host,port)['db']['coll'].find({key:val, k2:val2}, projection=[(key:1),(key2:1)])
try:
while True:
cursor.next()
except StopIteration:
# reach end of stream
finally:
cursor.close()
mongodb scala driver
dependency: org.mongodb.scala:mongo-scala-driver_2.11 or _2.12
SHIT!!!!! HOLY SHIT !!!!!!!! also mongodb casbah !!!!! SHIT !!!!!!!! 2018.3.22
mongodb spark connector
org.mongodb.spark:mongo-spark-connector_2.11:2.2.1
val sc = new SparkContext(new SparkConf().setAppName("myapp")
.set("spark.mongodb.input.uri", "mongodb://user:pass@host:port/db.collection"))
val rdd = MongoSpark.load(sc)
// 官网建议使用withPipeline(而非RDD.filter),不但能使数据在返回到rdd前过滤,还能在没有数据匹配时不引起异常,否则RDD.filter会导致NPE。
val aggregatedRdd = rdd.withPipeline(Seq(Document.parse("""{$match:{}""")))
如果不希望通过uri传入用户名密码认证信息,需要自定义MongoClientFactory,作为MongoConnector的构造参数,然后将MongoConnector作为MongoSpark.Builder的connector创建MongoSpark,之后调用toRdd获得MongoRDD。(注意这是版本spark-connector_2.11:2.2.1。
FAQ
sort排序失败:
Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit。
解决:在文档量过大时排序字段需建索引。org.mongodb:mongodb-driver-core:3.6.3与org.mongodb.spark:mongo-spark-connector_2.11:2.2.1存在兼容问题,可能导致NPE。
安装mongodb server、client
centos:
vim /etc/yum.repo.d/mongo.repo
填入内容:
name=MongoDB Repository
baseurl=http://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/x86_64/
gpgcheck=0
enabled=1
默认配置文件为/etc/mongod.conf,服务器绑定的网络接口配置在bindIp:上,默认为0.0.0.0,如果只想为本机服务,则配置为127.0.0.1,如果配置为局域网ip(如10.36.124.131)则只能在lan接口上服务,本机(127.0.0.1)没有服务,如果要在本机及lan接口上服务则用逗号连接两个ip,逗号后不得有空格(bindIp: 127.0.0.1,10.36.124.131)。
手动安装:
下载对系统版本的server安装包,
Windows系统下将mongodb安装为服务的命令:
mongod --config "C:\Program Files\MongoDB\Server\3.4\conf\mongo.conf" --serviceName MongoDB --install
其中mongo.conf由自己创建,window版无默认配置文件,配置文件中必须包含dbpath和logpath,dbpath文件夹需提前创建,否则mongod无法成功启动。
mongodb由MongoDB,Inc开发,公司曾用名“10gen”。
mongodb doc离线版下载,原提供pdf格式,现提供epub格式。
(待丰富)
Mongodb——文档数据库的更多相关文章
- Python操作MongoDB文档数据库
1.Pymongo 安装 安装pymongo: pip install pymongo PyMongo是驱动程序,使python程序能够使用Mongodb数据库,使用python编写而成: 2.Pym ...
- MongoDB系列三(Spring集成方案).
一.前言 MongoDB是最为流行的开源文档数据库之一.Spring Data MongoDB提供了三种方式在Spring应用中使用MongoDB: 通过注解实现对象-文档映射: 使用MongoTem ...
- 进阶-MongoDB 知识梳理
MongoDB 一.MongoDB简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式.Mo ...
- MongoDb进阶实践之七 MongoDB的索引入门
一.引言 好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关索引的文章.一说到"索引",用过关系型数据库的人都应该知道它是一个什么 ...
- MongoDb进阶实践之九 Mongodb的备份与还原
一.引言 前几天写了MongoDB数据库的聚合.一说到“聚合”,用过关系型数据库的人都应该知道它是一个什么东西,主要是用于对数据分类汇总和统计.大家都知道,做为DBA还有另一个重要的任务,那就是对数据 ...
- MongoDb进阶实践之八 MongoDB的聚合初探
一.引言 好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关聚合的文章.一说到“聚合”,用过关系型数据库的人都应该知道它是一个什么东西.关系型数据库有“聚合” ...
- [mongoDB] mongoDb
mongodb memcached redis kv数据库(key/value) mongodb 文档数据库,存储的是文档(Bson->json的二进制化). 特点:内部执行引擎为 ...
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
一.简介 Spring Data MongoDB 项目提供与MongoDB文档数据库的集成.Spring Data MongoDB POJO的关键功能区域为中心的模型与MongoDB的DBColle ...
- 在MVC程序中使用MongoDB数据库
.net项目中混搭数据库 安装和部署 C#中使用MongoDB MongoDb与关系型数据库区别 开机自启动 关系型数据库和非关系型数据口可以混搭 MongoDB是一个高性能,开源,无模式的,基于分布 ...
随机推荐
- 最小公倍数LCM
基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 输入2个正整数A,B,求A与B的最小公倍数. Input 2个数A,B,中间用空格隔开.(1<= A,B <= ...
- [bzoj3809]Gty的二逼妹子序列_莫队_分块
Gty的二逼妹子序列 bzoj-3809 题目大意:给定一个n个正整数的序列,m次询问.每次询问一个区间$l_i$到$r_i$中,权值在$a_i$到$b_i$之间的数有多少个. 注释:$1\le n\ ...
- 深入解析Microsoft Sql server 2008
http://blog.csdn.net/downmoon/article/details/5256548
- css3 transform对其他样式影响,(尤其是position:flixed)
1.transform 会为当前元素添加 position : relative 特性: 当 magin 为负值的时候,就会覆盖到前面的 元素, 然而如果给前面元素添加了transform 属性后,前 ...
- Jupyter Notebook: 解决build docker-stacks时conda太慢的问题
当想使用docker安装Jupyter Notebook时,有一个很好的项目是docker-stacks(https://github.com/jupyter/docker-stacks/tree/m ...
- ssh远程连接出现someone counld be eavesdropping on you right now 的错误
master主机通过ssh远程连接slaves机子时出现下述错误 解决的方法: 一.删除/root/.ssh/下的kown_hosts文件 二.在master机子上又一次运行scp id_dsa.pu ...
- FFmpeg总结(三)AV系列结构体之AVCodecContext
位置: 描写叙述:主要扩展API的结构体 New fields can be added to the end with minor version bumps. Removal, reorderin ...
- windows下写的脚本,在linux下执行失败
Windows中的换行符为CRLF, 即正则表达式的rn(ASCII码为13和10), 而Unix(或Linux)换行符为LF, 即正则表达式的n. 在Windows和Linux下协同工作的时候, 往 ...
- [Apple开发者帐户帮助]八、管理档案(2)创建临时配置文件(iOS,tvOS,watchOS)
创建临时配置文件以在设备上运行您的应用程序而无需Xcode.在开始之前,您需要一个App ID,一个分发证书和多个注册设备. 有关完整的临时配置文件工作流程,请转到Xcode帮助中的分发到已注册设备( ...
- [Swift通天遁地]九、拔剑吧-(15)搭建具有滑出、视差、3D变形等切换效果的引导页
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...