MongoDB**是一种面向文档的数据库管理系统,由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。2007年10月,MongoDB由10gen团队所发展。2009年2月首度推出。在高负载的状况下,添加更多的节点,能够保证服务器性能。MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档相似于 JSON 对象。字段值能够包含其余文档,数组及文档数组。php
优势java
缺点mysql
解压下载https://www.mongodb.com/download-center/community的ZIP包,并更改文件名为mongodb,在其同目录下建立文件夹data和data\db,log和mongo.log。git
mongod --dbpath D:\mongodb\data\db --logpath=D:\mongodb\log\mongodb.log --logappend
最后,再次打开cmd 进入cd mongodb\bin,执行下面命令:mongogithub
在浏览器中打开地址:正则表达式
用户名和密码链接到MongoDB,'username:password@hostname/dbname'sql
易懂的读取pretty(),mongodb
db.collection.remove( <query>, <justOne> )
db.col.find({key1:value1, key2:value2}).pretty()
>db.col.find( { $or: [ {key1: value1}, {key2:value2} ] } ).pretty()
db.COLLECTION_NAME.find().limit(NUMBER)
skip()方法来跳过指定数量的数据,skip方法一样接受一个数字参数做为跳过的记录条数。docker
db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
db.COLLECTION_NAME.find().sort({KEY:1})
db.COLLECTION_NAME.ensureIndex({KEY:1})
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
mongod --port 27017 --dbpath D:\mongodb\data\db --logpath=D:\mongodb\log\mongodb.log --replSet rs0
以上实例会启动一个名为rs0的MongoDB实例,其端口号为27017。shell
启动后打开命令提示框并链接上mongoDB服务。
在Mongo客户端使用命令rs.initiate()来启动一个新的副本集。
咱们可使用rs.conf()来查看副本集的配置
查看副本集姿态使用 rs.status() 命令
D:\mongodb\bin>mongo MongoDB shell version v4.1.11-262-gc237f4c connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("7109348e-cade-4128-af30-7cf8776302a9") } MongoDB server version: 4.1.11-262-gc237f4c # 添加副本集 > rs.add("mongod1.net:27017") 2019-05-30T18:57:26.058-0700 E QUERY [js] uncaught exception: Error: assert failed : no config object retrievable from local.system.replset : doassert@src/mongo/shell/assert.js:20:14 assert@src/mongo/shell/assert.js:152:9 rs.add@src/mongo/shell/utils.js:1441:5 @(shell):1:1 # 查看当前运行是不是主节点 > db.isMaster() { "ismaster" : false, "secondary" : false, "info" : "Does not have a valid replica set config", "isreplicaset" : true, "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 100000, "localTime" : ISODate("2019-05-31T01:57:40.632Z"), "logicalSessionTimeoutMinutes" : 30, "connectionId" : 1, "minWireVersion" : 0, "maxWireVersion" : 8, "readOnly" : false, "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(0, 0), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(0, 0) } # 启动一个新的副本集 > rs.initiate() # 查看副本集的配置 rs0:SECONDARY> rs.conf() # 查看副本集姿态 rs0:PRIMARY> rs.status()
MongoDB数据备份:mongodbdump
使用mongodump命令来备份MongoDB数据。该命令能够导出全部数据到指定目录中。mongodump命令能够经过参数指定导出的数据量级转存的服务器。
、
mongostat 和 mongotop 两个命令来监控MongoDB的运行状况。
环境配置,在Java程序中若是要使用MongoDB,你须要确保已经安装了Java环境及MongoDB JDBC 驱动。
import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.WriteConcern; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBCursor; import com.mongodb.ServerAddress; import java.util.Arrays; public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到 mongodb 服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到 mongodb 服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.createCollection("mycol"); System.out.println("Collection created successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到 mongodb 服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.createCollection("mycol"); System.out.println("Collection created successfully"); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到 mongodb 服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); BasicDBObject doc = new BasicDBObject("title", "MongoDB"). append("description", "database"). append("likes", 100). append("url", "//www.w3cschool.cn/mongodb/"). append("by", "w3cschool.cn"); coll.insert(doc); System.out.println("Document inserted successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到 mongodb 服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); DBCursor cursor = coll.find(); int i=1; while (cursor.hasNext()) { System.out.println("Inserted Document: "+i); System.out.println(cursor.next()); i++; } }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到Mongodb服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到你的数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); DBCursor cursor = coll.find(); while (cursor.hasNext()) { DBObject updateDocument = cursor.next(); updateDocument.put("likes","200") coll.update(updateDocument); } System.out.println("Document updated successfully"); cursor = coll.find(); int i=1; while (cursor.hasNext()) { System.out.println("Updated Document: "+i); System.out.println(cursor.next()); i++; } }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
public class MongoDBJDBC{ public static void main( String args[] ){ try{ // 链接到Mongodb服务 MongoClient mongoClient = new MongoClient( "localhost" , 27017 ); // 链接到你的数据库 DB db = mongoClient.getDB( "test" ); System.out.println("Connect to database successfully"); boolean auth = db.authenticate(myUserName, myPassword); System.out.println("Authentication: "+auth); DBCollection coll = db.getCollection("mycol"); System.out.println("Collection mycol selected successfully"); DBObject myDoc = coll.findOne(); coll.remove(myDoc); DBCursor cursor = coll.find(); int i=1; while (cursor.hasNext()) { System.out.println("Inserted Document: "+i); System.out.println(cursor.next()); i++; } System.out.println("Document deleted successfully"); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
MongoDB 的关系表示多个文档之间在逻辑上的相互联系。文档间能够经过嵌入和引用来创建联系。MongoDB 中的关系能够是:
一个用户能够有多个地址,因此是一对多的关系。
"_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address": [ { "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }, { "building": "170 A, Acropolis Apt", "pincode": 456789, "city": "Chicago", "state": "Illinois" }] }
数据保存在单一文档中,比较容易的获取很维护数据。 你能够这样查询用户的地址:
>db.users.findOne({"name":"Tom Benzamin"},{"address":1})
这种数据结构的缺点是,若是用户和用户地址在不断增长,数据量不断变大,会影响读写性能。
{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address_ids": [ ObjectId("52ffc4a5d85242602e000000"), ObjectId("52ffc4a5d85242602e000001") ] }
须要两次查询,第一次查询用户地址的对象id(ObjectId),第二次经过查询的id获取用户的详细地址信息。
>var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1}) >var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})
考虑如下 posts 集合的文档数据,包含了文章内容(post_text)及标签(tags):
{ "post_text": "enjoy the mongodb articles on w3cschool.cn", "tags": [ "mongodb", "w3cschool" ] }
咱们能够对 post_text 字段创建全文索引,这样咱们能够搜索文章内的内容:
>db.posts.ensureIndex({post_text:"text"})
如今咱们已经对 post_text 创建了全文索引,咱们能够搜索文章中的关键词w3cschool.cn:
>db.posts.find({$text:{$search:"w3cschool.cn"}})
如下命令返回了以下包含NoSQL关键词的文档数据:
D:\mongodb\bin>mongo MongoDB shell version v4.1.11-262-gc237f4c > show dbs admin 0.000GB config 0.000GB local 0.000GB myinfo 0.000GB w3cschooldb 0.000GB youj 0.000GB > use youj switched to db youj > db.col.find() { "_id" : ObjectId("5cef550377781c00a00de949"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } { "_id" : ObjectId("5cef690677781c00a00de94a"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } > db.col.ensureIndex({description:"text"}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } > db.col.find({$text:{$search:"NoSQL"}}) { "_id" : ObjectId("5cef690677781c00a00de94a"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } { "_id" : ObjectId("5cef550377781c00a00de949"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "w3cschool", "url" : "http://www.w3cschool.cn", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } >
删除已存在的全文索引,可使用 find 命令查找索引名:
>db.col.getIndexes()
经过以上命令获取索引名,本例的索引名为post_text_text,执行如下命令来删除索引:
> db.col.dropIndex('description_text')
使用 $regex 操做符来设置匹配字符串的正则表达式。
>db.posts.find({post_text:{$regex:"w3cschool.cn"}})
以上查询也能够写为:
>db.posts.find({post_text:/w3cschool.cn/})
若是检索须要不区分大小写,咱们能够设置 $options 为 $i。如下命令将查找不区分大小写的字符串 w3cschool.cn:
>db.posts.find({post_text:{$regex:"w3cschool.cn",$options:"$i"}})
集合中会返回全部包含字符串 w3cschool.cn 的数据,且不区分大小写:
{ "_id" : ObjectId("53493d37d852429c10000004"), "post_text" : "hey! this is my post on W3Cschool.cc", "tags" : [ "tutorialspoint" ] }
这在标签的实现上很是有用,若是你须要查找包含以 tutorial 开头的标签数据(tutorial 或 tutorials 或 tutorialpoint 或 tutorialphp), 你可使用如下代码:
>db.posts.find({tags:{$regex:"tutorial"}})
若是你的文档中字段设置了索引,那么使用索引相比于正则表达式匹配查找全部的数据查询速度更快。
若是正则表达式是前缀表达式,全部匹配的数据将以指定的前缀字符串为开始。例如: 若是正则表达式为^tut ,查询语句将查找以 tut 为开头的字符串。
GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。也是文件存储的一种方式,可是它是存储在MonoDB的集合中。GridFS 会将大文件对象分割成多个小的chunk(文件片断),通常为256k/个,每一个chunk将做为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。每一个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。
如下是简单的 fs.files 集合文档:
{ "filename": "test.txt", "chunkSize": NumberInt(261120), "uploadDate": ISODate("2014-04-13T11:32:33.557Z"), "md5": "7b762939321e146569b07f72c62cca4f", "length": NumberInt(646) }
如下是简单的 fs.chunks 集合文档:
{ "files_id": ObjectId("534a75d19f54bfec8a2fe44b"), "n": NumberInt(0), "data": "Mongo Binary Data" }
如今咱们使用 GridFS 的 put 命令来存储 mp3 文件。 调用 MongoDB 安装目录下bin的 mongofiles.exe工具。
打开命令提示符,进入到MongoDB的安装目录的bin目录中,找到mongofiles.exe,并输入下面的代码:
>mongofiles.exe -d gridfs put song.mp3
GridFS 是存储文件的数据名称。若是不存在该数据库,MongoDB会自动建立。Song.mp3 是音频文件名。使用如下命令来查看数据库中文件的文档:
>db.fs.files.find()
以上命令执行后返回如下文档数据:
{ _id: ObjectId('534a811bf8b4aa4d33fdf94d'), filename: "song.mp3", chunkSize: 261120, uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41", length: 10401959 }
咱们能够看到 fs.chunks 集合中全部的区块,如下咱们获得了文件的 _id 值,咱们能够根据这个 _id 获取区块(chunk)的数据:
>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})
以上实例中,查询返回了 40 个文档的数据,意味着mp3文件被存储在40个区块中。
MongoDB 没有像 SQL 同样有自动增加的功能, MongoDB 的id是系统自动生成的12字节惟一标识。但在某些状况下,咱们可能须要实现 ObjectId 自动增加功能。因为 MongoDB 没有实现这个功能,咱们能够经过编程的方式来实现,如下咱们将在 counters 集合中实现id字段自动增加。
如下 products 文档。id 字段实现 从 1,2,3,4 到 n 的自动增加功能。
{ "_id":1, "product_name": "Apple iPhone", "category": "mobiles" }
为此,建立 counters 集合,序列字段值能够实现自动长:
>db.createCollection("counters")
向 counters 集合中插入如下文档,使用 productid 做为 key:
{ "_id":"productid", "sequence_value": 0 }
sequence_value 字段是序列经过自动增加后的一个值。使用如下命令插入 counters 集合的序列文档中:
>db.counters.insert({_id:"productid",sequence_value:0})
建立函数 getNextSequenceValue 来做为序列名的输入, 指定的序列会自动增加 1 并返回最新序列值。在本文的实例中序列名为 productid 。
>function getNextSequenceValue(sequenceName){ var sequenceDocument = db.counters.findAndModify( { query:{_id: sequenceName }, update: {$inc:{sequence_value:1}}, new:true }); return sequenceDocument.sequence_value; }
使用 getNextSequenceValue 函数建立一个新的文档, 并设置文档 _id 自动为返回的序列值:
>db.products.insert({ "_id":getNextSequenceValue("productid"), "product_name":"Apple iPhone", "category":"mobiles"}) >db.products.insert({ "_id":getNextSequenceValue("productid"), "product_name":"Samsung S3", "category":"mobiles"})
使用 getNextSequenceValue 函数来设置 _id 字段。为了验证函数是否有效,咱们可使用如下命令读取文档:
>db.prodcuts.find()
以上命令将返回如下结果,咱们发现 _id 字段是自增加的:
{ "_id" : 1, "product_name" : "Apple iPhone", "category" : "mobiles"} { "_id" : 2, "product_name" : "Samsung S3", "category" : "mobiles" }