文章目录
NoSQL介绍
由于互联网的迅速发展,云计算与Web2.0这样大量的交互给数据库提出了更高的性能要求。传统的数据库(泛指SQL数据库),即关系型数据库虽然具备良好的事务管理,但在处理大量数据的应用时很难在性能上满足设计要求。
NoSQL就是为了解决当下大量高并发高要求的数据库应用需求。关系数据库具有严格的参照性,一致性,可用性,原子性,隔离性等特点,因此会产生一些例如表连接等操作,这样会大大降低系统的性能。而在当前很多应用场景下对性能的要求远远强于传统数据库关注的点,NoSQL就是为了解决大规模数据与多样数据总类等问题,尤其是其中大数据的相关问题。
NoSQL(Not Only SQL),它指的是非关系型数据库,是以key-value形式存储,和传统的关系型数据库不一样,不一定遵循传统数据库的一些基本要求,比如遵循SQL标准,ACID 属性,表结构等。
NoSQL的应用场景
- 数据模型比较简单
- 需要灵活性更强的IT系统
- 对数据库性能要求较高
- 不需要高度的数据一致性
- 对于给定的key,比较容易映射复杂的环境
建议使用NoSQL的场景:
- 对数据库高并发读写的需求
- 对海量数据的高效存储和访问技术
- 对数据库的高可扩展性和高可用性的需求
NoSQL与传统的数据库对比
非数据型数据库,没有行、列的概念。用JSON来存储数据。集合就相当于关系型数据中的“表”,文档就相当于“行”。
了解mongodb数据库
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。MongoDB的最大特点是它支持的查询语言非常强大,其语法特点类似于面向对象的语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它的特点是高性能,易部署,易使用,存储数据非常方便。
数据库的操作
Create操作
在mongodb中没有专门的语句来创建数据库和集合(collection),在我们想要创建时,语句如下:
创建一个数据库student
use student
使用某个数据库来存储集合,若是数据库不存在,那么会创建这个·数据库。
为student数据库创建一个名为info的集合
use stendent
db.student.insertOne({
name:"zhangsan",
age:34})
直接向某个集合插入一条文档,若文档不存在将会创建该文档并添加一条文档。
查询所有数据库
show dbs
查询某个数据库中的集合
use student
show collections
Read操作
查询集合中所有元素的方法;
db.inventory.find()
查询集合中所有文档
db.inventory.find( {} )
与find()查询的内容相同
相当于SQL数据库的查询语句:
SELECT * FROM inventory
查询 status 为 D 的 document:
db.inventory.find( { status: "D" } )
相当于如下SQL语句
SELECT * FROM inventory WHERE status = "D"
查询 status 为 “A” 或者 “B“ 的document;
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
注意:官方文档提示,尽管这一语句也可以使用 $ or 达到同一目的,但是在同一字段上执行相等性检查时,应该使用$ in运算符。
相当于如下SQL语句
SELECT * FROM inventory WHERE status in ("A", "D")
AND查询
查询status 等于 ”A“ 且 qty 小于($ lt)30
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
相当于以下SQL语句:
SELECT * FROM inventory WHERE status = "A" AND qty < 30
OR 查询
查询 status 等于 “A” 或者 qty 小于 ($lt) 30:
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
相当于以下SQL语句:
SELECT * FROM inventory WHERE status = "A" OR qty < 30
AND 与 OR 查询:
查询 status 等于 “A” 且 qty 小于($lt) 30 或者status 等于 “A” item 以 p 开头
相当于以下SQL语句:
SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")
Update 操作
update 操作指令;
- db.collection.updateOne() New in version 3.2
- db.collection.updateMany() New in version 3.2
- db.collection.replaceOne() New in version 3.2
为了更新文档,MongoDB提供了更新操作符(例如$ set)来修改字段值。 要使用更新运算符,请将以下形式的更新文档传递给更新方法:
更新第一个item 等于 ”paper“ 的document:
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)
操作过程:
- 使用$ set运算符将size.uom字段的值更新为“ cm”,将 status 的值更新为“ P”,
- 使用$ currentDate运算符将lastModified字段的值更新为当前日期。如果lastModified字段不存在,则$ currentDate将创建该字段。有关详细信息。
更新多个数据:
更新所有 ”qty“ 的值大于等于50的document
db.inventory.updateMany(
{ "qty": { $lte: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)
替换document
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)
Delete 操作
MongoDB提供以命令下删除集合文档的方法:
- db.collection.deleteOne() New in version 3.2
- db.collection.deleteMany() New in version 3.2
删除查找到的第一个status 为 ”D“ 的document:
db.inventory.deleteOne( { status: "D" } )
删除所有status 为 ”D“ 的document:
db.inventory.deleteMany({ status : "A" })
索引
索引支持在MongoDB中高效执行查询。没有索引,MongoDB必须执行集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的那些文档。如果查询存在适当的索引,则MongoDB可以使用该索引来限制它必须检查的文档数。
索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储一个特定字段或一组字段的值,按该字段的值排序。索引条目的排序支持有效的相等匹配和基于范围的查询操作。另外,MongoDB可以通过使用索引中的顺序来返回排序的结果。
下图说明了使用索引选择和排序匹配文档的查询:
从索引中查找符合条件的document再映射到真正的collection中,只需检查document的某一key值(且排好了序),这样极大的提高了检索效率。若是无索引,那么将会对collection中的所有文档的所有key值一一匹配。
从根本上说,MongoDB中的索引类似于其他数据库系统中的索引。MongoDB在集合 级别定义索引,并支持MongoDB集合中文档的任何字段或子字段的索引。
默认_id索引
在创建集合期间,MongoDB在_id字段上创建唯一索引。 _id索引可防止客户端为_id字段插入两个具有相同值的文档,你不能删除所有为_id的索引。
注意:在分片群集中,如果不使用_id字段作为分片键,则您的应用程序必须确保_id字段中值的唯一性,以防止发生错误。这通常是通过使用标准的自动生成的ObjectId来完成的。
创建索引
命令: db.collection.createIndex()
db.collection.createIndex( <key and index type specification>, <options> )
在 name 字段上创建单个键降序索引
db.collection.createIndex( { name: -1 } )
db.collection.createIndex方法仅在不存在相同规格的索引时创建索引。
具体详情可参考官方文档:
Index详情
node.js 操作数据库
连接数据库
- 在项目根目录生成一个package.json配置文件
npm init
- 下载mongodb驱动所依赖的包
npm install mongodb --save
- 下载正确版本的mongodb数据库,在项目中创建一个数据库文件夹,并启动mongodb数据库,启动命令如下:
mongod --dbpath=/data
- 创建一个新的app.js文件并添加以下代码,以使用MongoDB驱动程序尝试一些基本的CRUD操作。 添加代码以连接到服务器和数据库myproject:
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'myproject';
// Create a new MongoClient
const client = new MongoClient(url);
// Use connect method to connect to the Server
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
client.close();
});
插入document
将以下函数添加到app.js中,该函数使用insertMany方法将三个文档添加到documents集合中。
const insertDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Insert some documents
collection.insertMany([
{a : 1}, {a : 2}, {a : 3}
], function(err, result) {
assert.equal(err, null);
assert.equal(3, result.result.n);
assert.equal(3, result.ops.length);
console.log("Inserted 3 documents into the collection");
callback(result);
});
}
insert命令返回一个具有以下字段的对象:
- result包含来自MongoDB的结果文档
- ops包含带有添加的_id字段插入的文档
- connection包含用于执行插入的连接
查询所有document
添加一个查询,返回所有文档。
const findDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
callback(docs);
});
}
使用查询过滤器查找文档
const findDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Find some documents
collection.find({'a': 3}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs);
callback(docs);
});
}
仅返回与’a’:3匹配的文档。
更新document
const updateDocument = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Update document where a is 2, set b equal to 1
collection.updateOne({ a : 2 }
, { $set: { b : 1 } }, function(err, result) {
assert.equal(err, null);
assert.equal(1, result.result.n);
console.log("Updated the document with the field a equal to 2");
callback(result);
});
}
Remove document
删除字段a等于3的文档
const removeDocument = function(db, callback) {
// Get the documents collection
const collection = db.collection('documents');
// Delete document where a is 3
collection.deleteOne({ a : 3 }, function(err, result) {
assert.equal(err, null);
assert.equal(1, result.result.n);
console.log("Removed the document with the field a equal to 3");
callback(result);
});
}
为一个集合添加索引
索引可以改善应用程序的性能。以下函数在documents集合的a字段上创建索引。
const indexCollection = function(db, callback) {
db.collection('documents').createIndex(
{ "a": 1 },
null,
function(err, results) {
console.log(results);
callback();
}
);
};
调用数据库操作的方法
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'myproject';
const client = new MongoClient(url);
// Use connect method to connect to the server
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
insertDocuments(db, function() {
updateDocument(db, function() {
removeDocument(db, function() {
client.close();
});
});
});
insertDocuments(db, function() {
indexCollection(db, function() {
client.close();
});
});
});