文章目录

查询分析原子操作常用的原子操作命令高级索引索引数组字段索引子文档字段

索引注意事项

查询分析

$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 个字段。

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: