mongodb-13.查询,原子操作,高级索引
查询分析
$explain
$hint 运算符(也叫“强制查询优化器”)能够使用指定的索引来进行查询,以此来测试查询的性能。当您想要测试具有不同索引的查询性能时,此功能特别有用
原子操作
在MongoDB Compass中,用Mongosh中输入原生执行命令,回车用shift enter
>db.productDetails.insertOne({
product_name:'Sansung S3',
category:'mobiles',
product_total:5,
procuct_available:3,
product_bought_by:[
{
customer:'john',
date:'7-Jan-2014'
},
{
customer:'mark',
date:'8-Jan-2014'
}
]
})
{ acknowledged: true,
insertedId: ObjectId("63abf8322574a3d57b1902aa") }
db.productDetails.find()
{ _id: ObjectId("63abf8322574a3d57b1902aa"),
product_name: 'Sansung S3',
category: 'mobiles',
product_total: 5,
procuct_available: 3,
product_bought_by:
[ { customer: 'john', date: '7-Jan-2014' },
{ customer: 'mark', date: '8-Jan-2014' } ] }
原子操作findAndModify
db.productDetails.findAndModify({
query:{
_id:ObjectId("63abf8322574a3d57b1902aa"),
procuct_available:{$gt:0}
},
update:{
$inc:{
procuct_available:-1
},
$push:{
product_bought_by:{
customer:'yanwl',
date:'16-Dec-2022'
}
}
}
})
常用的原子操作命令
$set
用来指定一个键并更新键值,若键不存在则创建。
{ $set : { field : value } }
$unset
用来删除一个键。
{ $unset : { field : 1} }
$inc
用来对文档的某个数值类型的键值进行增减操作。
{ $inc : { field : value } }
$push
用来向文档中追加一些信息。
{ $push : { field : value } }
把 value 追加到 field 里面去,field 一定要是数组类型才行,如果 field 不存在,则会新增一个数组类型加进去。
$pushAll
与 $push 类似,它可以一次追加多个值到一个数组类型的字段内。
{ $pushAll : { field : value_array } }
$pull
从数组 field 内删除一个等于 value 的值。
{ $pull : { field : _value } }
$pop
删除数组的第一个或最后一个元素。
{ $pop : { field : 1 } }
$rename
修改字段的名称。
{ $rename : { old_field_name : new_field_name } }
$bit
位操作,integer 类型。
{$bit : { field : {and : 5}}}
偏移操作符
t.find() { “_id” : ObjectId(“4b97e62bf1d8c7152c9ccb74”), “title” : “ABC”, “comments” : [ { “by” : “joe”, “votes” : 3 }, { “by” : “jane”, “votes” : 7 } ] }
t.update( {‘comments.by’:‘joe’}, {KaTeX parse error: Expected '}', got 'EOF' at end of input: inc:{'comments..votes’:1}}, false, true )
t.find() { “_id” : ObjectId(“4b97e62bf1d8c7152c9ccb74”), “title” : “ABC”, “comments” : [ { “by” : “joe”, “votes” : 4 }, { “by” : “jane”, “votes” : 7 } ] }
高级索引
索引数组字段
db.users.insert(
{
"address": {
"city": "Hebei",
"country": "China",
"postcode": "000000"
},
"tags": [
"music",
"cricket",
"blogs"
],
"name": "bianchengbang"
}
)
{ acknowledged: true,
insertedIds: { '0': ObjectId("63ac02032574a3d57b1902ab") } }
在上面的文档中包含了一个名为 address 的子文档和一个名为 tags 的数组。 索引数组字段
假设要想根据集合内 tags 字段中的某个值来搜索用户文档,就需要我们为集合中的 tags 字段创建索引。想要在数组类型的字段上创建索引,需要为数组中的每个字段依次创建单独的索引。
在下面的示例中,当我们在 tags 字段上创建索引时,MongoDB 会自动在 music、cricket 和 blogs 等值上创建单独的索引。
>db.users.createIndex({
tags:1
})
>'tags_1'
>db.users.getIndexes()
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { tags: 1 }, name: 'tags_1' }
]
>db.users.find({tags:'cricket'}).pretty()
<{ _id: ObjectId("63ac02032574a3d57b1902ab"),
address: { city: 'Hebei', country: 'China', postcode: '000000' },
tags: [ 'music', 'cricket', 'blogs' ],
name: 'bianchengbang' }
>db.users.find({tags:'cricket'}).explain()
<{ queryPlanner:
{ plannerVersion: 1,
namespace: 'test.users',
indexFilterSet: false,
parsedQuery: { tags: { '$eq': 'cricket' } },
winningPlan:
{ stage: 'FETCH',
inputStage:
{ stage: 'IXSCAN',
keyPattern: { tags: 1 },
indexName: 'tags_1',
isMultiKey: true,
multiKeyPaths: { tags: [ 'tags' ] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: { tags: [ '["cricket", "cricket"]' ] } } },
rejectedPlans: [] },
serverInfo:
{ host: 'node4',
port: 27017,
version: '4.4.17',
gitVersion: '85de0cc83f4dc64dbbac7fe028a4866228c1b5d1' },
ok: 1,
'$clusterTime':
{ clusterTime: Timestamp({ t: 1672217366, i: 1 }),
signature:
{ hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
keyId: 0 } },
operationTime: Timestamp({ t: 1672217366, i: 1 }) }
索引子文档字段
创建子文档索引以前
>db.users.find({'address.city':'Hebei'})
<{ _id: ObjectId("63ac02032574a3d57b1902ab"),
address: { city: 'Hebei', country: 'China', postcode: '000000' },
tags: [ 'music', 'cricket', 'blogs' ],
name: 'bianchengbang' }
>db.users.find({'address.city':'Hebei'}).explain()
<{ queryPlanner:
{ plannerVersion: 1,
namespace: 'test.users',
indexFilterSet: false,
parsedQuery: { 'address.city': { '$eq': 'Hebei' } },
winningPlan:
{ stage: 'COLLSCAN',
filter: { 'address.city': { '$eq': 'Hebei' } },
direction: 'forward' },
rejectedPlans: [] },
serverInfo:
{ host: 'node4',
port: 27017,
version: '4.4.17',
gitVersion: '85de0cc83f4dc64dbbac7fe028a4866228c1b5d1' },
ok: 1,
'$clusterTime':
{ clusterTime: Timestamp({ t: 1672217756, i: 1 }),
signature:
{ hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
keyId: 0 } },
operationTime: Timestamp({ t: 1672217756, i: 1 }) }
创建索引
>db.users.ensureIndex({'address.city':1,'address.country':1,'address.postcode':1})
<[ 'address.city_1_address.country_1_address.postcode_1' ]
>db.users.find({'address.city':'Hebei'}).explain()
<{ queryPlanner:
{ plannerVersion: 1,
namespace: 'test.users',
indexFilterSet: false,
parsedQuery: { 'address.city': { '$eq': 'Hebei' } },
winningPlan:
{ stage: 'FETCH',
inputStage:
{ stage: 'IXSCAN',
keyPattern:
{ 'address.city': 1,
'address.country': 1,
'address.postcode': 1 },
indexName: 'address.city_1_address.country_1_address.postcode_1',
isMultiKey: false,
multiKeyPaths:
{ 'address.city': [],
'address.country': [],
'address.postcode': [] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds:
{ 'address.city': [ '["Hebei", "Hebei"]' ],
'address.country': [ '[MinKey, MaxKey]' ],
'address.postcode': [ '[MinKey, MaxKey]' ] } } },
rejectedPlans: [] },
serverInfo:
{ host: 'node4',
port: 27017,
version: '4.4.17',
gitVersion: '85de0cc83f4dc64dbbac7fe028a4866228c1b5d1' },
ok: 1,
'$clusterTime':
{ clusterTime: Timestamp({ t: 1672217966, i: 1 }),
signature:
{ hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
keyId: 0 } },
operationTime: Timestamp({ t: 1672217966, i: 1 }) }
索引注意事项
额外开销
每个索引都会占用一些空间,并且在每次执行插入、更新和删除等操作时也需要对索引进行操作,导致额外的开销。因此,如果您很少将某个集合用于读取操作,最好不要在集合中使用索引。
RAM 使用
由于索引存储在 RAM(内存)中,因此应确保索引的总大小不超过 RAM 的限制。如果总大小大于 RAM 的大小,那么 MongoDB 将删除一些索引,这就会导致性能下降。
查询限制
在以下的查询中,不能使用索引:
正则表达式或否定运算符,例如 n i n 、 nin、 nin、not 等;
算术运算符,例如 $mod 等;
$where 子句。
因此,建议经常使用 explain() 来检查查询时索引的使用情况。
索引键限制
从 2.6 版本开始,如果现有索引字段的值超过索引键的限制,那么 MongoDB 将不会创建索引。
插入超过索引键限制的文档
如果文档索引字段的值超过了索引键的限制,那么 MongoDB 不会将任何文档插入到集合中。mongorestore 和 mongoimport 实用程序也是如此。
最大范围
在定义索引时有以下几点需要注意:
集合的索引不能超过 64 个;
索引名称的长度不能超过 128 个字符;
复合索引最多可以拥有 31 个字段。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgkfiba
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13