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字段默认返回,若不需要该字段故需显式关闭。

不等于查询$nefind({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"。

  1. $elemMatch$ne:
db.Collection.find({array:{$elemMatch:{$ne:null}}})
  1. $where+js数组的.length
db.Collection.find({$where:"this.array.length>0"})
  1. $not$size
db.Collection.find({array: {$not: {$size: 0}}})
  1. $exists和'.'路径试图访问首元素
db.Collection.find({{'array.0': {$exists: 1}}})
  1. $exists$ne
db.Collection.find({ array: { $exists: true, $ne: [] } })
  1. $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的字段。

updatereplace在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

  1. sort排序失败

    Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit。

    解决:在文档量过大时排序字段需建索引。

  2. 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——文档数据库的更多相关文章

  1. Python操作MongoDB文档数据库

    1.Pymongo 安装 安装pymongo: pip install pymongo PyMongo是驱动程序,使python程序能够使用Mongodb数据库,使用python编写而成: 2.Pym ...

  2. MongoDB系列三(Spring集成方案).

    一.前言 MongoDB是最为流行的开源文档数据库之一.Spring Data MongoDB提供了三种方式在Spring应用中使用MongoDB: 通过注解实现对象-文档映射: 使用MongoTem ...

  3. 进阶-MongoDB 知识梳理

    MongoDB 一.MongoDB简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式.Mo ...

  4. MongoDb进阶实践之七 MongoDB的索引入门

    一.引言     好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关索引的文章.一说到"索引",用过关系型数据库的人都应该知道它是一个什么 ...

  5. MongoDb进阶实践之九 Mongodb的备份与还原

    一.引言 前几天写了MongoDB数据库的聚合.一说到“聚合”,用过关系型数据库的人都应该知道它是一个什么东西,主要是用于对数据分类汇总和统计.大家都知道,做为DBA还有另一个重要的任务,那就是对数据 ...

  6. MongoDb进阶实践之八 MongoDB的聚合初探

    一.引言 好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关聚合的文章.一说到“聚合”,用过关系型数据库的人都应该知道它是一个什么东西.关系型数据库有“聚合” ...

  7. [mongoDB] mongoDb

    mongodb memcached redis        kv数据库(key/value) mongodb 文档数据库,存储的是文档(Bson->json的二进制化). 特点:内部执行引擎为 ...

  8. Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)

    一.简介 Spring Data  MongoDB 项目提供与MongoDB文档数据库的集成.Spring Data MongoDB POJO的关键功能区域为中心的模型与MongoDB的DBColle ...

  9. 在MVC程序中使用MongoDB数据库

    .net项目中混搭数据库 安装和部署 C#中使用MongoDB MongoDb与关系型数据库区别 开机自启动 关系型数据库和非关系型数据口可以混搭 MongoDB是一个高性能,开源,无模式的,基于分布 ...

随机推荐

  1. 分块试水--CODEVS5037 线段树练习4加强版

    感觉这才算入门题吧..前面那些线段树练习,改几个字符就过了一定要搞成几道题.. n<=2e5的数列,给常数K<=2e5,m<=2e5个操作,区间加,问一个区间里K的倍数. 这题空间? ...

  2. 玲珑杯 ACM Round #12

    A =w= B 占坑 C 题意:有长度为n的序列A和长度为n的序列W,以及一个G,对于Ui,1<=Ui<=Wi,求Σgcd(Ai,Ui)=G的方案数,n<=1e3,Ai<=1e ...

  3. Javascript网址跳转方法

    第一种: window.location.href="http://www.baidu.com"; 第二种: window.navigate("http://www.ba ...

  4. 7、Java并发性和多线程-如何创建并运行线程

    以下内容转自http://ifeve.com/creating-and-starting-java-threads/: Java线程类也是一个object类,它的实例都继承自java.lang.Thr ...

  5. C#之反射(PropertyInfo类)

    1.引入命名空间:System.Reflection:程序集:mscorlib(在mscorlib.dll中) 2.示例代码(主要是getType().setValue().getValue()方法) ...

  6. openGl学习之基本图元

    从本篇開始,会给出一些代码实例,所以要配置好编译环境. 环境配置: vs2012下配置链接http://www.cnblogs.com/dreampursuer/archive/2014/05/27/ ...

  7. 设计四个线程,当中共两个线程每次对j添加1,另外两个线程每次对j降低1。循环100次,写出程序。

    package cn.usst.DataTest6; /** * 设计四个线程,当中共两个线程每次对j添加1,另外两个线程每次对j降低1.循环100次,写出程序. * @ * */ public cl ...

  8. 5.3.3 deque对象

    class collections.deque([iterable[, maxlen]]) 返回一个新双向队列,当有输入迭代器时.会从左至右地加入到队列里.假设没有输入參数,就创建一个空队列. deq ...

  9. NoSQL 世界交换数据的事实标准

    https://www.elastic.co/guide/cn/elasticsearch/guide/current/data-in-data-out.html An object is a lan ...

  10. 4.4系统,拍照-裁剪,resultCode返回0

    问题描述: take photo -> 拍照 -> 确定 -> 截图 -> 保存,此时返回给onActivityResult的resultCode是0,截图无效.我查看图片储存 ...