数据库-MongoDB篇

DB数据库 🖥 📊🖥 #

db

MongoDB笔记 #

学习网站:http://www.runoob.com/mongodb/mongodb-tutorial.html (其学习教程还挺可观,很多,不过还不清楚好不好)

安装 #

Docker 安装 4.4.12版本 #

pull:
	docker pull mongo:4.4.13
run:
    docker run -itd --name mongo --restart=always \
        -v /mongodb/datadb:/data/db \
        -p 27017:27017 \
        --network websafe-network \
        --privileged=true mongo:4.4.12

进入容器docker exec -it mongo bash后:

mongo
use admin

# db.createUser({user: "admin", pwd: "admin", roles: [{role: "root", db: "admin"}]})
# db.createUser({user: "admin", pwd: "admin", roles: [{role: "userAdminAnyDatabase", db: "admin"}]})
# 如果能auth就不用createUser了
db.auth("admin", "admin")

网上传的将 MONGO_INITDB_ROOT_PASSWORDMONGO_INITDB_ROOT_USERNAME传入环境变量的方式,在mongo4.4.12 和 4.4.13上都不好使。

数据迁移 #

insert into device_data_current select * from device_data;

使用 mysqldump #

很慢 很大 很方便 很!不好!使用!在使用–host时 下面命令没一次正常工作的,很难受

mysqldump -h192.168.0.25 -u{user} -p{passwd} {dbname} {tablename} > {tablename}.sql
sed -i 's/{tablename}/{new_tablename}/g' {tablename}.sql
mysql -u{user} -p{passwd} {dbname} < {table}.sql

# 增加条数限制
bash-4.2# mysqldump -u{user} -p{passwd} test demo --host {host} --where="true limit 5000" > demo.sql

还是用自己写的脚本好使 sql_one2one.py

注意事项 #

Mongo 数据库锁 #

mongo只提供库级粒度锁,所以一个写操作锁定时,其他读写操作都等待… 所以这个导致了Mongo多线程写操作反而没有一个线程写来的快?

前台建立索引时,Mongo需占用一个写锁(且不同上述、不会临时放弃) 为避免此问题需采用background方式

    db.posts.ensureIndex({user_id: 1})  #此方式将引起全面战争

    db.posts.ensureIndex({user_id: 1} {background: 1}) # 这个就比较和平

操作命令简单记录 #

创建、插入 #

use DATABASE_NAME   #如果数据库不存在,则创建数据库,否则切换到指定数据库。
show dbs        #查看所有数据库“name    size”

刚创建的数据库,如没有内容则不现实在其中

db.runoob.insert({"name":"教程"})       #插入数据

删除 #

db.dropDatabase()       #删除当前数据库,如未选择则删除test
db.collection.drop()        #删除集合
db.site.drop()          #:如删除site集合

插入文档 #

db.COLLECTION_NAME.insert(document)

db.col.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',     
    url: 'http://www.runoob.com',       
    tags: ['mongodb', 'database', 'NoSQL'], 
    likes: 100
    })      # 例如这样

db.col.find() # 查看已插入文档

也可以将document=括号里要插入内容,然后插入document变量,效果一样。

3.2版本新加 #
db.collection.insertOne()       #向指定集合中插入一条文档数据
db.collection.insertMany()  #向指定集合中插入多条文档数据

插入单条数据
var document = db.collection.insertOne({"a": 3})

document { “acknowledged” : true, “insertedId” : ObjectId(“571a218011a82a1d94c02333”) }

插入多条数据    
var res = db.collection.insertMany([{"b": 3}, {'c': 4}])

res { “acknowledged” : true, “insertedIds” : [ ObjectId(“571a22a911a82a1d94c02337”), ObjectId(“571a22a911a82a1d94c02338”) ] }

更新、添加文档 #

db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})      
#更新标题

db.collection.save(     
#通过传入的文档来替换已有文档
<document>,
{
writeConcern: <document>
})

参数说明: document : 文档数据。 writeConcern : 可选,抛出异常的级别。

eg: 实例中替换了 _id 为 56064f89ade2f21f36b03136 的文档数据:

db.col.save({
"_id" : ObjectId("56064f89ade2f21f36b03136"),
"title" : "MongoDB",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "Runoob",
"url" : "http://www.runoob.com",
"tags" : [
    "mongodb",
    "NoSQL"
],
"likes" : 110

})

导入csv文件 #

mongoimport --db Trader_1Min_Db --collection Au(T+D) --type csv --file 
D:\\IFData\\md_Au(T+D)_20170101_20170531\\md_Au(T+D)_2017010301.csv 
--headerline --upsert --ignoreBlanks

注意需要另开一个命令行,在其中运行。 2017-10-25T08:43:40.917+0800 E QUERY [thread1] SyntaxError: missing ; before statement @(shell):1:16 否则就是这个错误

-d    指定把数据导入到哪一个数据库中
-c    指定把数据导入到哪一个集合中
--type    指定导入的数据类型   csv/tsv  逗号或者tab分割值
--file       指定从哪一个文件中导入数据
--headerline    仅适用于导入csv,tsv格式的数据,表示文件中的第一行作为数据头
--upsert  以新增或者更新的方式来导入数据
--f  导入字段名
--ignoreBlanks 忽略空白符

导出 #

mongoexport -d test -c students -o students.dat 
connected to: 127.0.0.1 exported 9 records
# 指明导出格式为csv
mongoexport -d test -c students --csv -f classid,name,age -o students_csv.dat 
connected to: 127.0.0.1 exported 9 records   

添加 #

db.collectionName.update({}, {$set:{'key' : value}}, false, true);

#

.update

更改字段名称 #

db.CollectionName.update({}, {$rename : {"OldName" : "NewName"}}, false, true)
# false为如不存在update记录,是否插入新的纪录  
# ture位置为更新全部数据,如设定false 则为只更新第一条
# 另外 没有输入名称时没有输全,也会显示查找,但不会执行更改

统配 #

db.CollectionName.update(<query>, <update>,{upsert : <boolean>, multi : <boolean>, 
writeConcern : <document>})
# query : update 查找条件,类似sql update查询内where后面的
# update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查
#>询内set后面的
# upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插
#>入,默认是false,不插入。
# multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把
#>按条件查出来多条记录全部更新。
# writeConcern :可选,抛出异常的级别。
eg #
db.col.update({'title':'MongoDB'},{$set:{'title':'IamNewTitle'}})

删除文档 #

remove()函数是用来移除集合中的数据。

db.collection.remove(
<query>,
<justOne>
)
2.6版以后 #
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
})

参数说明: query :(可选)删除的文档的条件。 justOne : (可选)如果设为 true 或 1,则只删除一个文档。 writeConcern :(可选)抛出异常的级别。

db.col.remove({})   #删除所有 (就很恐怖)

查询文档 #

操作格式范例RDBMS中的类似语句
等于{<key>:<value>}db.col.find({"by":"教程"}).pretty()where by = '教程'
小于{<key>:{$lt:<value>}}db.col.find({"likes":{$lt:50}}).pretty()where likes < 50
小于或等于{<key>:{$lte:<value>}}db.col.find({"likes":{$lte:50}}).pretty()
大于{<key>:{$gt:<value>}}db.col.find({"likes":{$gt:50}}).pretty()
大于或等于{<key>:{$gte:<value>}}db.col.find({"likes":{$gte:50}}).pretty()
不等于{<key>:{$ne:<value>}}db.col.find({"likes":{$ne:50}}).pretty()where likes != 50
And #

find可以传入多个键(key),逗号隔开:

db.col.find({key1:value1, key2:value2}).pretty()
db.col.find({"by":"教程", "title":"MongoDB "}).pretty()
#类似于
WHERE by='教程' AND title='MongoDB '
Or #
db.test.find({$[{key1:value1},(key2:value2)]}).pretty()     #注意小中大括号😰
db.col.find({"likes": {$gt:50}, $or: [{"by": "教程"},{"title": "MongoDB "}]})
And 与 Or #
db.col.find({"likes": {$gt:50}, $or: [{"by": "教程"},{"title": "MongoDB "}]})
#类似于(其中pretty()是显示样式)
where likes>50 AND (by = '教程' OR title = 'MongoDB ‘

简写说明 #

$gt——–greater than>
$gte———gt equal>=
$lt——–less than<
$lte———lt equal<=
$ne———–not equal!=
$eq——–equal=
Type #
db.col.find({"title" : {$type : 2}})    #获取“col”集合中title为String的数据

对照表:

类型数字备注
Double1
String2
Object3
Array4
Binary data5
Undefined6已废弃。
Object id7
Boolean8
Date9
Null10
Regular Expression11
JavaScript13
Symbol14
JavaScript (with scope)15
32-bit integer16
Timestamp17
64-bit integer18
Min key255Query with -1.
Max key127
Limit() Skip()方法 #
db.col.find({},{"title":1,_id:0}).limit(2)

参数说明: “title”后1为判断语句,表示是否只查询“title”内容0为否,显示这条的全部信息。_id的0亦为判断表示是否显示“_id”内容。limit为限制搜索信息条数。

db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
skip(NUMBER)        #NUMBER为阶跃,即每隔几条数据来搜索

排序 #

db.COLLECTION_NAME.find().sort({KEY:1})     #KEY后数字可为1OR-1,升序OR降序
db.col.find({},{"title":1,_id:0}).sort({"likes":-1}     #按“likes”降序排序


MongoDB 索引 (建立索引干嘛……) #

ensureIndex() 方法 #

db.COLLECTION_NAME.ensureIndex({KEY:1})
# Key 值为要创建的索引字段,1为指定按升序创建索引,降序-1

聚合 #

aggregate()方法 #

db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
#类似于
select by_user, count(*) from mycol group by by_user

输出结果: { “_id” : “Neo4j”, “num_tutorial” : 1 } { “_id” : “runoob.com”, “num_tutorial” : 2 } { “_id” : null, “num_tutorial” : 1 }

参数说明:“$by_user” 即为分类依据,并打印出来(如上)。 num_tutorial 仅为显示提示,可以更改为任意提示甚至汉字。 $sum : 1 其中1为每次计数值,即重复一次加几。1+1+1+1…… :重复一次加1;0.1+0.1+0.1……重复一次加0.1。这个意思

计算符: #
表达式描述实例
$sum计算总和。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg计算平均值db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min获取集合中所有文档对应值得最小值。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max获取集合中所有文档对应值得最大值。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push在结果文档中插入值到一个数组中。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet在结果文档中插入值到一个数组中,但不创建副本。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first根据资源文档的排序获取第一个文档数据。db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last根据资源文档的排序获取最后一个文档数据db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

条件操作符 #

$gt     大于
$lt     小于
$gte        大于等于
$lte        小于等于

eg: #

db.col.find({likes : {$gte : 100}})
# 查询“col”集合中"likes"大于100的数据
# 比较与 `SQL       Select * from col where likes >=100;`

取前n条数据 #

.find().limit(n)

执行顺序 #

skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 
然后是 skip(),最后是显示的 limit()。

数据导出 #

mongoexport -d *** -c *** -o ***
# -d 后为 dbName
   -c 后为 collectionName
   -o 后为 outputFileName 导出文件名

名字都不用加引号,直接上的~, 然后导出格式都是json 那样,不管后缀是什么用文本打开都是一个样子——骗鬼👻

数据导入 #

 mongoimport -h 127.0.0.1 -p 27017 -d Trader_1Min_Db -c ag1806 --file 
/home/ian/Downloads/ag1806.json

Linux 下使用Robo3T错误 #

错误最后字段为:已放弃 (核心已转储)

mkdir ~/robo-backup
mv robo3t-1.1.1-linux-x86_64-*/lib/libstdc++* 

~/robo-backup/robo3t-1.1.1-linux-x86_64-*/bin/robo3t 移动备份之后即可运行

For Python #

PyMongo #

from pymongo import MongoClient
client = MongoClient("localhost", 27017)
client.server_info()    
# 查看信息,检测是否成功连接
db = client["someData"]
collection = db.zn1801_30Min
# 两种命名方式,一种是直接.     一种是使用“”

乖乖的用双引号,因为,在这里的单双引号是区分的… 我现在也懒得去管它是字符字符串的什么鬼。┏┛墓┗┓…(((m -__-)m

insert #

collection.insert( {"name":"text" } )

find #

d = {u'Volume':{'$gte':50353,'$lte':50355}}
a = collection.find(d)

最小与最大,另外,find出来的东西是数据库指针,需要用for...in...来循环取出内容来

查询库名 #

from pymongo import MongoClient
client = MongoClient('localhost', 27017)
client.database_names()

[u’Trader_1Min_Db’, u’Trader_30Min_Db’, u’Trader_Tick_Db’, u’VnTrader_Log_Db’, u’VnTrader_Position_Db’, u’admin’, u’local’, u’someData’, u’test']

查询集合名 #

collectionNames = client[dbName].collection_names()
print collectionNames

使用 #

其读写速度还是可以的… 二十万条数据查询的话不到一秒,然而… 频繁多量的读取,再加上不断地往其中写入就出问题了…… 卡的极慢…简直恐怖(数个小时的延迟 怕不怕)。(当然以上情况是完全没有做任何优化的情况(直接insertfind),不知道优化之后会怎样) 另外不知道不增加条数,去增加内容会怎样…… emm 果然还是缓存比较好用…在高速多量多频次的情况下还是用内存里面不去手动做任何保存比较好。 等积攒够量之后再去保存,就好比文件压缩不去一个个小文件传输一个道理。