MongoDB概念
MongoDB 基本概念指的是学习 MongoDB 最先应该了解的词汇,比如 MongoDB 中的"数据库"、"集合"、"文档"这三个名词:
文档(Document): 文档是 MongoDB 中最基本的数据单元,由键值对组成,类似于 JSON 格式,可以存储不同字段,字段的值可以包括其他文档,数组和文档数组。(相当于mysql每一行就是一个文档)
集合(Collection): 集合指的是文档组(类似于 Mysql 中的表的概念),里面可以存储许多文档。
数据库(Database): MongoDB 中可以存在多个数据库,每个数据库中中用有不同的集合与用户权限,这样可以供不同的项目组使用不同的数据库。
常用查询语句
查找所有文档
查询集合(比如 users
集合)中的所有文档:这个查询不带任何条件,返回集合中的所有文档。
db.users.find()
分页查询
查询并限制返回10条
db.users.find().limit(10)
查询用户,跳过前 20 个结果,并限制返回的结果数量为 10:.skip(20)
用于跳过前 20 个文档,.limit(10)
用于限制查询结果数量。
db.users.find().skip(20).limit(10)
排序查询结果
查询所有用户并按年龄升序排序:
db.users.find().sort({ age: 1 })
查找匹配特定条件的文档
查询所有年龄等于 25 的用户:
db.users.find({ age: 25 })
这里,{ age: 25 }
是一个查询条件,表示筛选出所有 age
字段值为 25 的文档。
模糊查询
假设您有一个名为users的表,其中包含名为name的字段,您想要对这个字段进行模糊搜索。您可以使用正则表达式来匹配包含特定字符串的文档。
db.users.find({ name: { $regex: /your_pattern_here/ } })
如果您想要不区分大小写地进行搜索,可以在正则表达式中末尾添加i标志:
db.users.find({ name: { $regex: /your_pattern_here/i } })
指定字段返回
假设有一个名为 users 的集合,文档结构包含 name、email 和 age 字段。如果你只想检索 name 和 email 字段,可以使用 .projection 方法来实现
限定返回结果字段
db.users.find({}, { projection: { name: 1, email: 1, _id: 0 } })
这里 { name: 1, email: 1, _id: 0 } 指明返回的文档中应包含 name 和 email 字段,并排除 MongoDB 默认的 _id 字段
包含查询
如果你使用的是 MongoDB Shell 或者类似的接口,并且想要查询 department 等于 "Sales" 且 job_title 包含在某个列表中(如 'Manager' 或 'Associate')的文档,你可以这样写:
db.employees.find({
department: "Sales",
job_title: { $in: ["Manager", "Associate"] }
});
这里的 **in** 操作符类似于 SQL 中的 **IN**,用于匹配字段值是否存在于指定数组中。不包含是nin
大小查询
如果你需要构造一个 MongoDB 查询,以满足字段同时大于等于(gte**)和小于等于(**lte)一个特定值的条件,同时另一个字段等于($eq)特定的值,你可以使用组合查询。以下是一个具体示例,假设我们需要查询一个集合中,年龄在20岁到30岁之间(包含20岁和30岁),并且名字等于"John"的文档。
db.users.find({
db.users.find({
age: { $gte: 20, $lte: 30 }, // 年龄大于等于20且小于等于30
name: { $eq: "John" } // 名字等于John
});
计数查询结果
计算年龄等于 25 的用户数量:countDocuments
函数统计匹配查询条件的文档数量
db.users.countDocuments({ age: 25 })
或者
查询名字是 "John" 或者 "Jane" 的用户:$or
是逻辑操作符,允许多个查询条件中的任意一个成立时,文档就会被选中。
db.users.find({ $or: [{ name: "John" }, { name: "Jane" }] })
高级查询
分组
MongoDB 提供了一个强大的聚合框架,类似于 SQL 中的 GROUP BY
功能。这个聚合框架可以用来执行包括数据分组、计算汇总统计等复杂的数据处理任务。在 MongoDB 中,这通常是通过 aggregate
方法来实现的,其中可以使用多种聚合阶段(比如 $group
、$match
、$sort
等)来构建复杂的查询和数据处理流程。
使用 $group
进行分组统计
假设你有一个名为 orders
的集合,每个文档包含 customer
和 amount
字段,分别代表客户名和订单金额。如果你想计算每个客户的总订单金额,可以使用以下的聚合查询:
db.orders.aggregate([
{
$group: {
_id: "$customer",
totalAmount: { sum: "amount" }
}
}
]);
在这个聚合查询中:
$group
: 是用来将文档分组的阶段。_id: "$customer"
:指定分组的键,这里使用$customer
字段,意味着所有具有相同customer
字段值的文档会被分到同一组。totalAmount: { $sum: "$amount" }
:为每个组计算总金额,$sum
操作符会加总每个组中的amount
字段值。
结果:只显示_id和totalAmount字段
如果你想先过滤某些文档,再进行分组,可以这样做:
db.orders.aggregate([
{ $match: { status: "shipped" } },
{
$group: {
_id: "$customer",
totalAmount: { sum: "amount" }
}
},
{ $sort: { totalAmount: -1 } }
]);
这里:
$match
: 过滤阶段,只有status
字段为 "shipped" 的文档才会被处理。$group
: 同上,按客户分组并计算总金额。$sort
: 排序阶段,按totalAmount
字段降序排序结果。
注意事项
MongoDB 的聚合操作非常强大,但也需要考虑性能问题,特别是在处理大数据集时。确保你的文档结构和索引策略适合你的聚合查询,以优化查询性能。
连表
在 MongoDB 中,连表查询通常是通过 $lookup
聚合管道操作符来实现的。这个操作符可以让你在一个聚合查询中从另一个集合中查询和合并数据,类似于 SQL 中的 JOIN 操作。
基本使用方法:
假设你有两个集合:orders
和 products
。orders
集合中的每个文档包含一个 productId
字段,你想将 orders
集合中的每个订单与 products
集合中相应的产品详情进行关联。以下是如何使用 $lookup
来实现这种关联:
db.orders.aggregate([
{
$lookup: {
from: "products", // 要联接的集合名称
localField: "productId", // 本地集合(orders)用于联接的字段
foreignField: "_id", // 外部集合(products)用于联接的字段
as: "productDetails" // 将联接查询结果添加到该字段
}
}
]);
解释:
from
: 指定要联接的另一个集合的名称。localField
: 当前集合(发起$lookup
的集合)中用于联接的字段。foreignField
: 被联接集合中用于匹配localField
的字段。as
: 将外部集合的查询结果存储在每个输出文档的哪个字段下。
高级用法
从 MongoDB 3.6 开始,$lookup
支持使用管道,这让你可以在 $lookup
内部执行更复杂的查询,包括过滤、添加字段、限制返回字段等操作。
db.orders.aggregate([
{
$lookup: {
from: "products",
let: { orderProduct: "$productId" }, // 定义变量 orderProduct
pipeline: [ // 使用 pipeline 对 products 进行操作
{ $match:
{ $expr:
{ eq: \["_id", "$$orderProduct"] } // 使用变量进行匹配
}
},
{ $project: { name: 1, price: 1 } } // 限制返回的字段
],
as: "productDetails"
}
}
]);