RDB:数据库 → 表(列) → 行
Mongo:数据库 → 集合 → 文档
SQL和Mongodb的关系映射表(里面还有一些增删改查等等操作与SQL的对应的语句):
https://www.mongodb.com/docs/manual/reference/sql-comparison/
mongodb数据格式是以BSON(二进制 json)存储的。https://www.mongodb.com/docs/v5.0/core/document/#documents
因此它本身就是用json格式来操作数据,底层在存储的时候改为BSON,它的文件数据格式如下:
mongodb最大的特点就是,数据库和集合不用创建就能插入数据,而且集合中数据也不管你有那些字段,随便插入。这点非常适合爬虫,因为你爬取的数据有些字段它不一定有。
mongodb他没有redis快,但是比RDB快,因为他读写都是先经过内存,然后内存数据再单独存储在磁盘。
注意:上面说的情况在默认存储引擎,因为Mongodb可以更改存储引擎,具体看https://www.mongodb.com/docs/manual/core/storage-engines/
数据库的操作
数据库的创建
mongodb使用use <数据库名>
进行创建和选择数据库,如果选择的数据库不存在,则自动帮你创建数据库
use <数据库名>
查看所有数据库
show dbs
删除数据库
// 先选择数据库
use test001
// 再执行删除操作
db.dropDatabase()
集合的操作
创建集合
正常情况下集合都不用手动创建,因为mongodb不需要集合存在就可以使用,你插入数据时它就会帮你自动创建。
一般只有在需要创建固定类型的集合的时候才需要手动创建。
什么是固定集合呢?
固定集合就是固定集合的大小体积或者固定集合中文档数量的一个集合,比较像时序数据库,一旦数据达到集合的限制,那么新数据就会覆盖最旧的数据,就像一个时钟一样循环。
集合创建语法:
db.createCollection(<集合名>, {capped: true, size: <集合的大小(字节)>, max: <集合中文档的最大数量>})
参数 | 类型 | 说明 |
capped | bool | 是否为固定集合,capped为true时,必须指定size的值。 |
size | int | 集合的固定大小(单位:字节) |
max | int | 可选。集合中文档的最大数量。 |
查看所有集合
show collections | show tables
删除集合
db.<集合名>.drop()
实例:
// 创建test001数据库
use test001
// 查看所有的数据库
show dbs
// 创建spider_data集合
db.createCollection("spider_data")
// 查看当前数据库下的所有集合
show tables
// 删除spider_data集合
db.spider_data.drop()
文档操作-增、删、改、查
增删改查等官方文档:
https://www.mongodb.com/docs/v5.0/crud/
增删改查的操作符:
https://www.mongodb.com/docs/manual/reference/operator/update/
插入数据(增)
语法:
//3.2之前的版本用:
db.<集合名>.insert(<document>, {OPTIONS})
//3.2后可以用insertOne、insertMany。。。不过谁用3.2之前版本呀
// 插入一条数据
db.<集合名>.insertOne(
<document>,
{
writeConcern: <document>
}
)
// 插入多条数据
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
ordered:指定是否按顺序写入,默认 true,按顺序写入。
实例:
use test001
// 可以使用变量,这里的语法就是js的语法.....
let input_name = "笑答"
// 向test集合中插入一条数据
db.test.insertOne({
name: input_name, // 可以直接使用变量的值
age: 26,
hobby: "basketball"
});
// 插入多条数据
db.test.insertMany([
{name: "下排名", age: 17},
{name: "小红", age: 27},
{name: "小榄", age: 25},
])
查找数据(查)
https://www.mongodb.com/docs/v5.0/crud/#read-operations
查看过滤的条件和操作符:比如逻辑运算符and\or\not、比较运算符gt\lt\gte等等。
https://www.mongodb.com/docs/v5.0/reference/operator/query/
实例:
// 查找全部数据(你不给条件就等于全部啦)
db.test.find()
/**
* 查找, 比较运算符(相当where条件)
**/
// 查找出第一条符合条件的数据
db.test.findOne({age: {$in: [18, 17]}}) // 因为时findone,即便你有多条数据返回它页只显示一个,相当于limit 1
// 大于、 大于等于
db.test.find({age: {$gt: 18}})
db.test.find({age: {$gte: 18}})
// 小于、小于等于
// SELECT * FROM test WHERE age < 18
db.test.find({age: {$lt: 18}})
db.test.find({age: {$lte: 18}})
// 等于
db.test.find({age: 18})
db.test.find({age: {$eq: 18}})
// in 在集合内
// SELECT * FROM test WHERE age IN(18, 17, 26)
db.test.find({age: {$in: [18, 17, 26]}})
// not in 不在集合内
//SELECT * FROM test WHERE age NOT IN(18, 17, 26)
db.test.find({age: {$nin: [18, 17, 26]}})
// 逻辑运算符 and
// 相当于 SELECT * FROM test WHERE age > 18 AND hobby IS NULL
db.test.find({
age: {$gt: 18},
hobby: {$exists: false}
})
// 逻辑运算or
//SELECT * FROM test WHERE age > 22 OR hobby IS NOT NULL
db.test.find({
$or: [
{age: {$gt: 22}},
{hobby: {$exists: true}}
]
})
// 混合and 和 or 运算
//SELECT * FROM test WHERE age > 20 AND (name="小米" or hobby is not null)
db.test.find({
$and: [
{age: {$gt: 20}},
{
$or: [
{hobby: {$exists: true}},
{name: "小米"},
]
}
]
})
db.test.find({
age: {$gt: 20},
$or: [
{hobby: {$exists: true}},
{name: "小米"},
]
})
// 使用正则表达式查询
/**
* 正则表达式使用^匹配速度会快很多,否则默认是模糊类型的匹配。
* 如果你不使用$结尾,就是只要前面匹配就行,后面不管你是什么样子
**/
db.test.find({
name: /^小.$/
})
db.test.find({
name: /^小./ // 这样只要是小开头然后只要后面还有一个字符的都匹配出来,而不是说刚好匹配两个字符
})
db.test.find({
name: /^小.{2}$/ // 小字开头,然后后面跟随刚好两个任意字符结尾
})
// distinct
db.people.distinct( "status" )
修改数据(改)
https://www.mongodb.com/docs/v5.0/crud/#update-operations
修改数据的操作符(就是用来指定要怎么修改数据):
https://www.mongodb.com/docs/manual/reference/operator/update/
/**
* 修改语句
*
* db.集合(表).updateOne({查询条件},{新的数据})
* db.集合(表).updateMany({查询条件},{新的数据})
* db.collection.replaceOne() 查找并替换符合条件的第一个。
**/
// 更新指定字段(updateOne只更新第一条符合条件的记录)
db.test.updateOne(
// query
{name: "王五"},
// update
{
$set: {age: 88} // 使用$set来更新指定的字段的值
}
)
db.test.updateOne(
// query
{name: "你麻痹"},
// update
{
$set: {age: 88} // 使用$set来更新指定的字段的值
},
{
upsert: true
}
)
// updateMany更新全部符合条件的记录
db.test.updateMany(
// query
{age: 27},
// update
{
$set: {age: 88} // 使用$set来更新指定的字段的值
}
)
删除数据(删)
/**
* 删除
*
* db.test.deleteOne()
* db.test.deleteMany()
**/
db.test.deleteOne({
name: "小"
})
db.test.deleteMany({
name: "小"
})
投影(查询时只返回指定字段)
这玩意就是等同于你执行SQL语句SELECT <字段1>,<字段2> FROM <表名>
/**
* 只查询指定字段(投影)
*
* db.集合.find({查询条件}, {字段: 0|1, 字段: 0|1,...})
*
* key:字段
* val: 是否显示,用0、1控制
* 字段就是要指定的字段是否显示
* 0:不显示
* 1: 显示
**/
// _id列默认是显示的,即便你没有让他显示
db.test.find({}, {name: 1, age: 1})
// 除非你指定它不显示
db.test.find({}, {_id: 0, name: 1, age: 1})
排序sort
就是SQL中的order_by
/**
* 排序
*
* db.集合.find().sort({
* 字段: 1|-1 // -1表示倒序,1表示正序
* })
**/
// 按照age字段倒序
db.test.find().sort({age: -1})
count统计
/**
* count() 统计
**/
// 查询age大于20的数据,并统计数量
//SELECT count(*) from test where age > 20
db.test.find({age: {$gt: 20}}).count()
limit限制、skip偏移
/***
* limit 和 skip
* 也就是sql的limit和offset
*/
//SELECT * FROM test LIMIT 5 OFFSET 2
db.test.find().limit(5).skip(2)
db.test.find().skip(2).limit(5) // 顺序无关要紧...只有在聚合使用聚合管道的时候顺序才会有影响(管道后面说)
聚合操作(聚合管道、分组groupby等)
聚合操作简单点说就是根据聚合管道中的顺序,依次执行其中的聚合命令,对文档数据进行处理后输出。
示意图:
常用的聚合操作命令:
$group
: 分组$match
: 过滤,就是find中的过滤条件$project
: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果$sort
: 排序$limit
: 限制聚合管道返回的⽂档数$skip
: 跳过指定数量的⽂档(offset)- 其他:https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/
聚合管道中可以使用的各种运算符:
实例:
// 插入预先准备好的数据
db.test02.insertMany([
{
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
},
])
//select by_user, count(likes) as num_count from test02 group by by_user
db.test02.aggregate([
{
$group: {
// _id: "$by_user", // _id是用于指定按那个字段进行分组
_id: {
"by_user": "$by_user", // 也可以给分组的列指定一个名字by_user,然后下面$project可以使用by_user别名
},
num_count: {$sum: "$likes"} // num_count 是自己命名的别名,后面时对$likes字段进行$sum操作(也就是count)。
}
},
{
$project: { // project就是投影显示
"by_user": "$_id.by_user", // by_user时显示的名称,引用的值是上面管道操作后的$_id.by_user
"like_count": "$num_count",
"_id": 0 // 让”_id“列不显示
}
}
])
**// 实例2:**
db.orders.insertMany( [
{ _id: 0, name: "Pepperoni", size: "small", price: 19,
quantity: 10, date: ISODate( "2021-03-13T08:14:30Z" ) },
{ _id: 1, name: "Pepperoni", size: "medium", price: 20,
quantity: 20, date : ISODate( "2021-03-13T09:13:24Z" ) },
{ _id: 2, name: "Pepperoni", size: "large", price: 21,
quantity: 30, date : ISODate( "2021-03-17T09:22:12Z" ) },
{ _id: 3, name: "Cheese", size: "small", price: 12,
quantity: 15, date : ISODate( "2021-03-13T11:21:39.736Z" ) },
{ _id: 4, name: "Cheese", size: "medium", price: 13,
quantity:50, date : ISODate( "2022-01-12T21:23:13.331Z" ) },
{ _id: 5, name: "Cheese", size: "large", price: 14,
quantity: 10, date : ISODate( "2022-01-12T05:08:13Z" ) },
{ _id: 6, name: "Vegan", size: "small", price: 17,
quantity: 10, date : ISODate( "2021-01-13T05:08:13Z" ) },
{ _id: 7, name: "Vegan", size: "medium", price: 18,
quantity: 10, date : ISODate( "2021-01-13T05:10:13Z" ) }
] )
db.orders.aggregate( [
// Stage 1: 根据披萨的尺寸进行过滤
{
$match: { size: "medium" }
},
// Stage 2: 将符合Stage1的剩余文档按照name进行分组,然后统计分组中每个组的quantity总数
{
$group: { _id: "$name", totalQuantity: { $sum: "$quantity" } }
}
] )
Example output: 输出示例:
[
{ _id: 'Cheese', totalQuantity: 50 },
{ _id: 'Vegan', totalQuantity: 10 },
{ _id: 'Pepperoni', totalQuantity: 20 }
]
标签:入门,Mongodb,age,db,id,熟悉,test,find,name
From: https://www.cnblogs.com/juelian/p/17559731.html