[mongo] {第二部分}MongoDB CRUD v1
CRUD操作可create, read, update和delete documents。
create
创建或插入操作会将新documents添加到collection中。如果该集合当前不存在,则插入操作将创建该集合。
MongoDB提供了以下将文档插入集合的方法:
- db.collection.insertOne() 3.2版中的新功能
- db.collection.insertMany() 3.2版中的新功能
在MongoDB中,插入操作的目标是单个collection。MongoDB中的所有写操作在单个文档级别上都是原子性的 。
Insert
插入一个文档
db.collection.insertOne()将单个 文档插入集合中。
以下示例将一个新文档插入到 inventory集合中。如果文档未指定_id字段,则MongoDB将_id具有ObjectId值的字段添加到新文档中。
db.inventory.insertOne(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
insertOne()返回包含新插入的文档的_id字段值的文档。
要检索刚刚插入的文档,请查询集合:
db.inventory.find( { item: "canvas" } )
插入多个文档
3.2版中的新功能。
db.collection.insertMany()可以将多个 文档插入一个集合中。将文档数组传递给该方法。
下面的示例将三个新文档插入到 inventory集合中。如果文档未指定 _id字段,则MongoDB将_id具有ObjectId值的字段添加到每个文档。
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
{ item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
{ item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])
Insert Behavior
集合创建(Collection Creation)
如果该集合当前不存在,则插入操作将创建该集合。
_id字段
在MongoDB中,存储在集合中的每个文档都需要一个唯一的 _id字段作为主键。如果插入的文档省略了该_id字段,则MongoDB会自动为该字段生成一个ObjectId_id。
这也适用于通过upsert:true通过更新操作插入的文档。
原子性
MongoDB中的所有写操作都是单个文档级别的原子操作。
写确认(Write Acknowledgement)
对于写问题,您可以指定MongoDB向写操作请求的确认级别。
Insert Methods
MongoDB提供了以下将文档插入到集合中的方法:
插入单个文档到集合中 |
|
db.collection.insertMany() 插入多个文档到集合中 |
|
db.collection.insert()插入单个或多个文档到集合中 |
插入文档的其他方式
- 以下方法还可以将新文档添加到集合中:
- db.collection.update() when used with the upsert: true option.
- db.collection.updateOne() when used with the upsert: true option.
- db.collection.updateMany() when used with the upsert: true option.
- db.collection.findAndModify() when used with the upsert: true option.
- db.collection.findOneAndUpdate() when used with the upsert: true option.
- db.collection.findOneAndReplace() when used with the upsert: true option.
- db.collection.save().
- db.collection.bulkWrite().
See the individual reference pages for the meth
查询
读取操作从 集合中检索文档; 即查询文档集合。MongoDB提供了以下方法来从集合中读取文档:
您可以指定查询或筛选条件以标识要返回的文档。
列出集合中的所有文档
要选择集合中的所有文档,请将空文档作为查询过滤器参数传递给find方法。查询过滤器参数确定选择条件:
db.inventory.find( {} )
此操作对应于以下SQL语句:
SELECT * FROM inventory
指定相等条件
要指定相等条件,请<field>:<value> 在查询过滤器文档中使用表达式 :
{ <field1>: <value1>, ... }
以下示例从inventory集合中选择status等于的所有文档"D":
db.inventory.find( { status: "D" } )
此操作对应于以下SQL语句:
SELECT * FROM inventory WHERE status = "D"
指定条件下使用查询运算符
文档可以使用查询运算符,以指定在以下形式的条件:
{ <field1>: { <operator1>: <value1> }, ... }
以下示例从inventory 集合中检索status等于"A"或的所有文档"D":
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
注意
尽管可以使用$or运算符表示此查询,但是在同一字段上执行相等性检查时,请使用$in运算符而不是$or运算符。
该操作对应于以下SQL语句:
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
AND条件
复合查询可以为集合文档中的多个字段指定条件。隐式地,逻辑AND连接将复合查询的子句连接起来,以便查询选择集合中符合所有条件的文档。
以下示例检索inventory 集合中status等于"A" 和 qty小于($lt)的所有文档30:
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
该操作对应于以下SQL语句:
SELECT * FROM inventory WHERE status = "A" AND qty < 30
OR条件
使用$or运算符,您可以指定一个复合查询,该查询将每个子句与一个逻辑连接符连接在一起,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
注意
使用比较运算符的查询 需进行Type Bracketing。
AND和OR条件
在下面的例子中,status等号"A" 和 任一 qty小于($lt)30 或 item开始字符为p:
{
<update operator>: { <field1>: <value1>, ... },
<update operator>: { <field2>: <value2>, ... },
...
}
该操作对应于以下SQL语句:
SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")
注意
MongoDB支持正则表达式$regex查询以执行字符串模式匹配。
Update
Update操作修改在集合已存在的文档。MongoDB提供了以下方法来更新集合的文档:
- db.collection.updateOne() 3.2版中的新功能
- db.collection.updateMany() 3.2版中的新功能
- db.collection.replaceOne() 3.2版中的新功能
在MongoDB中,更新操作针对单个集合。MongoDB中的所有写操作都是单个文档级别的原子操作。
您可以指定标识要更新的文档的条件或过滤规则。这些过滤器使用与读取操作相同的语法。
更新集合中的文档
要更新文档,MongoDB提供了 诸如的更新操作符$set来修改字段值。
要使用更新运算符,请将以下形式的更新文档传递给更新方法:
{
<update operator>: { <field1>: <value1>, ... },
<update operator>: { <field2>: <value2>, ... },
...
}
$set如果该字段不存在,则某些更新运算符(例如)将创建该字段。
注意:
从MongoDB 4.2开始,MongoDB可以接受聚合管道来指定要进行的修改而不是更新文档。有关详细信息,请参见方法参考页。
更新单个文档
以下示例使用集合db.collection.updateOne()上的 方法 inventory更新等于的第一个文档 :item 为 "paper"
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)
更新操作:
- 使用$set操作员更新的值 size.uom字段"cm"和值status 字段"P",
- 使用$currentDate运算符将lastModified字段的值更新为当前日期。如果 lastModified字段不存在, $currentDate将创建该字段。
更新多个文档
3.2版中的新功能。
以下示例使用集合db.collection.updateMany() 上的方法inventory更新qty小于的所有文档 50:
db.inventory.updateMany(
{ "qty": { $lt: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)
更新操作:
- 使用$set操作员更新的值 size.uom字段"in"和值status 字段"P",
- 使用$currentDate运算符将lastModified字段的值更新为当前日期。如果 lastModified字段不存在, $currentDate将创建该字段。
替换一个文档
要替换除_id 字段以外的文档的所有内容,请将一个全新的文档作为第二个参数传递给 db.collection.replaceOne()。
替换文档时,替换文档必须仅由字段/值对组成;即不包括更新运算符表达式。
替换文档可以具有与原始文档不同的字段。在替换文档中,_id由于该_id字段是不可变的,因此可以省略该字段;但是,如果确实包含该_id字段,则该 字段必须与当前值具有相同的值。
下面的示例替换集合中的第一个文档, inventory其中:item:
"paper"
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)
Delete
删除操作从集合中删除文档。MongoDB提供了以下删除集合文档的方法:
- db.collection.deleteOne() 3.2版中的新功能
- db.collection.deleteMany() 3.2版中的新功能
在MongoDB中,删除操作的目标是单个collection。。
您可以指定条件或过滤器,以标识要删除的文档。这些过滤器使用与读取操作相同的语法。
删除所有文档
要删除集合中的所有文档,请将空的筛选器文档传递 {}给 db.collection.deleteMany()方法。
下面的示例从 集合中删除所有文档inventory:
db.inventory.deleteMany({})
该方法返回具有操作状态的文档
删除所有符合条件的文档
您可以指定标准或过滤器,以标识要删除的文档。该过滤器使用相同的语法,读操作。
要指定相等条件,请<field>:<value> 在查询过滤器文档中使用表达式 :
db.inventory.deleteMany({})
复制
复制的
{ < field1 >: { <运算符1 >: < value1 > }, ... }
要删除所有符合删除条件的文档,请将过滤器参数传递 给该 deleteMany()方法。
以下示例从inventory 该status字段等于的集合中删除所有文档"A":
db.inventory.deleteMany({ status : "A" })
该方法返回具有操作状态的文档。
仅删除一个符合条件的文档
要最多删除一个与指定过滤器匹配的文档(即使多个文档可能与指定过滤器匹配),请使用db.collection.deleteOne()方法。
下面的示例删除第一文件,其中status是 "D":
db.inventory.deleteOne( { status: "D" } )
索引
即使从集合中删除所有文档,删除操作也不会删除索引。
Delete Methods
MongoDB提供了以下删除集合文档的方法:
即使多个文档可能与指定过滤器匹配,也最多删除一个与指定过滤器匹配的文档。3.2版中的新功能。 |
|
删除所有与指定过滤器匹配的文档。3.2版中的新功能。 |
|
删除单个文档或与指定过滤器匹配的所有文档。 |
其他方式
以下方法也可以从集合中删除文档:
findOneAndDelete() 提供了一个排序选项。该选项允许删除按指定顺序排序的第一个文档。
db.collection.findAndModify()提供排序选项。该选项允许删除按指定顺序排序的第一个文档。
批量写(Bulk Write)
概述
MongoDB使客户端能够批量执行写操作。批量写入操作会影响单个集合。MongoDB允许应用程序确定批量写入操作所需的可接受级别。
3.2版中的新功能。
db.collection.bulkWrite()方法提供了执行批量插入,更新和删除操作的能力。MongoDB还支持通过批量插入db.collection.insertMany()。
有序与无序操作
批量写操作可以有序或无序。
通过有序操作,MongoDB串行执行操作。如果在写操作之一的处理过程中发生错误,MongoDB将返回而不处理列表中任何剩余的写操作。
使用不排序的操作,MongoDB可以并行执行操作,但是不能保证此行为。如果在写操作之一的处理过程中发生错误,MongoDB将继续处理列表中剩余的写操作。
在分片集合上执行操作的有序列表通常比执行无序列表要慢,因为对于有序列表,每个操作必须等待上一个操作完成。
默认情况下,bulkWrite()执行ordered 操作。要指定unordered写操作,请在选项文档中进行设置 ,ordered
:
false。
bulkWrite()方法
bulkWrite() 支持以下写操作:
每个写操作都bulkWrite()作为文档传递到数组中。
例如,以下执行多个写操作:
try {
db.characters.bulkWrite(
[
{ insertOne :
{
"document" :
{
"_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
}
}
},
{ insertOne :
{
"document" :
{
"_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
}
}
},
{ updateOne :
{
"filter" : { "char" : "Eldon" },
"update" : { $set : { "status" : "Critical Injury" } }
}
},
{ deleteOne :
{ "filter" : { "char" : "Brisbane" } }
},
{ replaceOne :
{
"filter" : { "char" : "Meldane" },
"replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
}
}
]
);
}
catch (e) {
print(e);
}
批量插入分片集合的策略
大量的大容量插入操作(包括初始数据插入或常规数据导入)可能会影响分片群集的性能。对于批量插入,请考虑以下策略:
预拆分集合
如果分片集合为空,则该集合只有一个初始块,该块位于单个分片上。然后,MongoDB必须花一些时间来接收数据,创建拆分并将拆分的块分发到可用的分片。为了避免这种性能成本,您可以按照拆分碎片中的拆分块中的说明预先拆分集合 。
无序写入mongos
要提高对分片群集的写入性能,请使用 bulkWrite()可选参数ordered 设置为false。mongos可以尝试同时将写入发送到多个分片。对于空集合,首先按照分片群集中的分割块中的说明预分割集合 。
避免单调
如果您的分片键在插入过程中单调增加,则所有插入的数据都将到达集合中的最后一块,该块将始终以单个分片结尾。因此,群集的插入容量将永远不会超过该单个分片的插入容量。
如果您的插入量大于单个分片可以处理的插入量,并且如果您无法避免单调增加的分片键,那么请考虑对应用程序进行以下修改:
- 反转分片键的二进制位。这样可以保留信息,并避免将插入顺序与值序列的增加关联起来。
- 交换第一个和最后一个16位字以“随机”插入。
- 点赞
- 收藏
- 关注作者
评论(0)