Introduction
Recent projects use mongo logs for data statistics. Being obsessed with non-relational databases, I bought a copy of MongoDB Actual Warfare and studied it for a while. Record the learning notes and share them.
Get ready
I installed the latest version of Mono on my Linux server. Record another problem with the installation link.
Linux Installation mongo https://blog.51cto.com/136418...
I encountered a privilege problem when I wanted to see the state of the database.
> db.serverStatus() { "ok" : 0, "errmsg" : "not authorized on admin to execute command { serverStatus: 1.0, lsid: { id: UUID(\"bbda7ede-9e92-492b-ae2f-f0f641fba261\") }, $db: \"admin\" }", "code" : 13, "codeName" : "Unauthorized" }
Solution: https://www.cnblogs.com/alexz...
If we look at the above solution, we need to enter the mongo shell mode (admin) again by entering a command:
mongo -u 'admin' -p '123' --authenticationDatabase 'admin'
Basic concepts
mysql | mongo | explain |
---|---|---|
database | database | data base |
table | collection | aggregate |
row | document | File |
column | field | field |
Mongo stores data in BSON format, similar to JSON, as follows:
{ "_id": ObjectId("5d399bb2b52d6dc8a4ff6b42"), "name": "pjjlt" }
If the primary key is not specified, a _id (12 bytes in length) is generated by default. The generation rule is: 4 bytes timestamp + 3 bytes machine Id+2 bytes process Id+3 bytes random number.
Mongo operation
Basic operation
> show dbs #View all databases and usage admin 0.000GB config 0.000GB local 0.000GB > use pjjlt #Switch to the pjjlt library and find that it was not created switched to db pjjlt > db #View which database is currently being operated on pjjlt > db.myCollection.insert({"name":"pjjlt"}) #Insert a data into the myCollection collection of the pjjlt library (without this collection, create it) WriteResult({ "nInserted" : 1 }) > show collections #View all collections under this library (pjjlt) myCollection > db.myCollection.find() #Query a collection of data { "_id" : ObjectId("5d399bb2b52d6dc8a4ff6b42"), "name" : "pjjlt" } #The reason for the length of the article is not to demonstrate the following operation, but to explain it directly. >db.myCollection.drop() #Delete a collection >db.dropDatabase() #Delete a database >db.serverStatus() #Look at the server status information. (Look at the engine right here. You can see that the default engine for mongo4 is wiredtiger.) >db.stats() #Simple information in the current database allows you to see how many collections are in this database >db.myCollection.stats() #View the basic information of a collection >db.runCommand() #You can execute a function() method >db.help() #View all operations at the database level >db.myCollection.help() #View all operations at the collection level >db.listCommands() #List all database commands
Data insertion
Data insertion can be divided into insert and save methods. Specific all methods, you can enter a piece of code, and then press the tab key twice to see.
#Two TAB keys, look at the following methods. Insert implements the following two methods: insert one or more > db.myCollection.insert db.myCollection.insert( db.myCollection.insertMany( db.myCollection.insertOne( #Insert a record > db.myCollection.insert({"name":"haha"}) WriteResult({ "nInserted" : 1 }) #Insert multiple records and output more detailed information > db.myCollection.insert([{"name":"hehe"},{"name":"heihei"}]) BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 2, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] }) #See how much data there is in the myCollection collection > db.myCollection.count() 4 #Looking at the content again, _id is the primary key for automatic generation. > db.myCollection.find() { "_id" : ObjectId("5d399bb2b52d6dc8a4ff6b42"), "name" : "pjjlt" } { "_id" : ObjectId("5d3a6bafd40e94efd747de7b"), "name" : "haha" } { "_id" : ObjectId("5d3a6c3fd40e94efd747de7c"), "name" : "hehe" } { "_id" : ObjectId("5d3a6c3fd40e94efd747de7d"), "name" : "heihei" } #Take a look at the insertion function of save, which specifies _id #Update if _id exists, insert if not, similar to insert > db.myCollection.save({"name":"save0"}) WriteResult({ "nInserted" : 1 }) > db.myCollection.save([{"name":"save1"},{"name":"save2"}]) BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 2, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] }) > db.myCollection.find() { "_id" : ObjectId("5d399bb2b52d6dc8a4ff6b42"), "name" : "pjjlt" } { "_id" : ObjectId("5d3a6bafd40e94efd747de7b"), "name" : "haha" } { "_id" : ObjectId("5d3a6c3fd40e94efd747de7c"), "name" : "hehe" } { "_id" : ObjectId("5d3a6c3fd40e94efd747de7d"), "name" : "heihei" } { "_id" : ObjectId("5d3a927fb4d620841817e434"), "name" : "save0" } { "_id" : ObjectId("5d3a92a2b4d620841817e436"), "name" : "save1" } { "_id" : ObjectId("5d3a92a2b4d620841817e437"), "name" : "save2" }
Data modification
Data modification includes command save and update, in which update has the function of local update and replacement update.
#First look at the save method, specify _id, and modify it > db.myCollection.save({"_id":ObjectId("5d3a92a2b4d620841817e437"),"name":"save3"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.myCollection.find() { "_id" : ObjectId("5d399bb2b52d6dc8a4ff6b42"), "name" : "pjjlt" } { "_id" : ObjectId("5d3a6bafd40e94efd747de7b"), "name" : "haha" } { "_id" : ObjectId("5d3a6c3fd40e94efd747de7c"), "name" : "hehe" } { "_id" : ObjectId("5d3a6c3fd40e94efd747de7d"), "name" : "heihei" } { "_id" : ObjectId("5d3a927fb4d620841817e434"), "name" : "save0" } { "_id" : ObjectId("5d3a92a2b4d620841817e436"), "name" : "save1" } { "_id" : ObjectId("5d3a92a2b4d620841817e437"), "name" : "save3" } #Then look at the update method. Like insert, update implements the following two methods > db.myCollection.update db.myCollection.update( db.myCollection.updateMany( db.myCollection.updateOne(
Look at the update grammar
db.collection.update( <query>, #The query condition of update, similar to the section after where of sql update statement <update>, #update objects and some updated operators can also be understood as following the sql update statement set { upsert: <boolean>, #Optionally, this parameter means that if there is no update record, whether to insert objNew, true is insert, default is false, no insert multi: <boolean>, #Optionally, mongodb defaults to false, updates only the first record found, and if this parameter is true, updates all the records found on condition. writeConcern: <document> #Optional, level of throwing exception } )
Then back to the example, for illustration purposes, we create a new collection user
#Create a new document for a new collection > db.user.insert({"username":"pjjlt","age":25}) WriteResult({ "nInserted" : 1 }) > db.user.find().pretty() { "_id" : ObjectId("5d3aa1fcb4d620841817e438"), "username" : "pjjlt", "age" : 25 } # ok, change the age of pjjlt to 18, and use the keyword $set. I will show you the effect of not using this keyword later. > db.user.update({"_id" : ObjectId("5d3aa1fcb4d620841817e438")},{$set:{"age":18}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.user.find().pretty() { "_id" : ObjectId("5d3aa1fcb4d620841817e438"), "username" : "pjjlt", "age" : 18 } #If you use $set as a local update, if you don't use it, replace the update. To differentiate, we've taken the new domain city as an example. > db.user.update({"_id" : ObjectId("5d3aa1fcb4d620841817e438")},{"city":"SJZ"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.user.find().pretty() { "_id" : ObjectId("5d3aa1fcb4d620841817e438"), "city" : "SJZ" } #It was found that the original data had disappeared because it had been completely replaced.
Data deletion
Data deletion can use deleteMany, deleteOne, remove
# Two Tab s > db.user.delete db.user.deleteMany( db.user.deleteOne( # Delete no data > db.user.deleteOne({"_id" : ObjectId("5d3aa1fcb4d620841817e438")}) { "acknowledged" : true, "deletedCount" : 1 } > db.user.find().pretty() > # Add a few more data > db.user.find() { "_id" : ObjectId("5d3ab2f8b4d620841817e439"), "username" : "pjjlt", "age" : 25 } { "_id" : ObjectId("5d3ab2fdb4d620841817e43a"), "username" : "pjjlt1", "age" : 25 } { "_id" : ObjectId("5d3ab302b4d620841817e43b"), "username" : "pjjlt2", "age" : 25 } { "_id" : ObjectId("5d3ab322b4d620841817e43c"), "username" : "pjjlt3", "age" : 18 }
Remote grammar
db.collection.remove( <query>, #Optional, Query Conditions { justOne: <boolean>, #Optionally, set to true or 1, to delete only one document, set to false, to delete all matching documents, default to false writeConcern: <document> #Optional, level of throwing exception } )
Let's go back to the example and delete it. Disk space needs to be freed manually
> db.user.remove({"age" : 25}) WriteResult({ "nRemoved" : 3 }) > db.user.find() { "_id" : ObjectId("5d3ab322b4d620841817e43c"), "username" : "pjjlt3", "age" : 18 } #Manual release of disk space > db.repairDatabase() { "ok" : 1 }
Data query
Almost all businesses are related to queries.
Range query operator
operator | describe |
---|---|
$lt | less than |
$gt | greater than |
$lte | Less than or equal to |
$gte | Greater than or equal to |
Prepare a large data set and add 1000 numbers to the numbers set
#The first three points are automatically generated and have no impact on the code. Please ignore them. > for(i=0;i<1000;i++){ ... db.numbers.save({num:i}); ... } WriteResult({ "nInserted" : 1 }) #Test one $lt, and the others are the same. > db.numbers.find({"num":{$lt:5}}) { "_id" : ObjectId("5d3ac7b7b4d620841817e43d"), "num" : 0 } { "_id" : ObjectId("5d3ac7b8b4d620841817e43e"), "num" : 1 } { "_id" : ObjectId("5d3ac7b8b4d620841817e43f"), "num" : 2 } { "_id" : ObjectId("5d3ac7b8b4d620841817e440"), "num" : 3 } { "_id" : ObjectId("5d3ac7b8b4d620841817e441"), "num" : 4 }
set operator
operator | describe |
---|---|
$in | If any parameter references a set, then matching |
$all | If all parameters are referenced in the collection and used in documents containing arrays, then matching |
$nin | If no parameters are in the reference set, match |
#Insert a record > db.tools.insert({tools:["AAA","BBB","CCC","DDD","EEE"]}) WriteResult({ "nInserted" : 1 }) #Check it out > db.tools.find() { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ] } #Find it through $in > db.tools.find({tools:{ ... $in:["AAA","FFF","ZZZ"] ... } ... }) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ] } #all Search Test > db.tools.find({tools:{ $all:["AAA","FFF","ZZZ"] } }) > db.tools.find({tools:{ $all:["AAA","BBB"] } }) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ] } #$nin search test > db.tools.find({tools:{ $nin:["AAA","BBB"] } }) > db.tools.find({tools:{ $nin:["ZZZ","YYY"] } }) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ] }
Boolean operator
operator | describe |
---|---|
$ne | Mismatched parameters |
$not | Mismatch result |
$or | A conditional match holds. |
$nor | All conditions do not match |
$and | All conditions match |
$exists | Judging whether an element exists |
#Next, for the example above, use $ne > db.tools.find({tools:{$ne:"AAA"}}) > db.tools.find({tools:{$ne:"ZZZ"}}) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ] } #not looks like a condition reversal. > db.tools.find({tools:{$not:{$in:["AAA"]}}}) > db.tools.find({tools:{$not:{$in:["ZZZ"]}}}) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ] } #To demonstrate the following functions, add a new domain to the document you just saw > db.tools.update({"_id" : ObjectId("5d3ad78eb4d620841817e825")},{$set:{"city":"SJZ"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.tools.find().pretty() { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ], "city" : "SJZ" } #$or > db.tools.find( {$or:[ {tools:{$in:["AAA"]}}, {"city":"BJ"} ]} ) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ], "city" : "SJZ" } #All conditions of $nor do not match > db.tools.find( {$nor:[ {tools:{$in:["ZZZ"]}}, {"city":"BJ"} ]} ) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ], "city" : "SJZ" } #$and > db.tools.find( {$and:[ {tools:{$in:["AAA"]}}, {"city":"BJ"} ]} ) > db.tools.find( {$and:[ {tools:{$in:["AAA"]}}, {"city":"SJZ"} ]} ) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ], "city" : "SJZ" } #$exists # Does tools Set Exist tools Domain > db.tools.find({"tools":{$exists:true}}) { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ], "city" : "SJZ" } # Does the tools collection not exist in the tools domain? > db.tools.find({"tools":{$exists:false}}) >
Array operator
operator | describe |
---|---|
$elemMatch | If all the words provided are in the same subdocument, then match |
$size | If the subdocument array size is the same as the text value provided, then the matching |
#Insert new documents into a new collection > db.products.insert({addresses:[{name:"home",city:"sjz"},{name:"work",city:"bj"}]}) WriteResult({ "nInserted" : 1 }) > db.products.find().pretty() { "_id" : ObjectId("5d3ae3763d2312bc3a0be84c"), "addresses" : [ { "name" : "home", "city" : "sjz" }, { "name" : "work", "city" : "bj" } ] } #elemMatch needs subdocuments > db.products.find({addresses:{$elemMatch:{"name":"home","city":"sjz"}}}) { "_id" : ObjectId("5d3ae3763d2312bc3a0be84c"), "addresses" : [ { "name" : "home", "city" : "sjz" }, { "name" : "work", "city" : "bj" } ] } #size > db.products.find({"addresses":{$size:1}}) > db.products.find({"addresses":{$size:2}}) { "_id" : ObjectId("5d3ae3763d2312bc3a0be84c"), "addresses" : [ { "name" : "home", "city" : "sjz" }, { "name" : "work", "city" : "bj" } ] }
Sort Page Separator
operator | describe |
---|---|
$sort | Sort 1 in positive order; - 1 in retrospect |
$limit | How many bars are displayed? |
$skip | Jump too much data |
Note that like MySQL, skip operates on large numbers very slowly and needs to be narrowed down in advance.
#Use the numbers collection > db.numbers.find().sort({"num":-1}).skip(33).limit(9) { "_id" : ObjectId("5d3ac7b8b4d620841817e803"), "num" : 966 } { "_id" : ObjectId("5d3ac7b8b4d620841817e802"), "num" : 965 } { "_id" : ObjectId("5d3ac7b8b4d620841817e801"), "num" : 964 } { "_id" : ObjectId("5d3ac7b8b4d620841817e800"), "num" : 963 } { "_id" : ObjectId("5d3ac7b8b4d620841817e7ff"), "num" : 962 } { "_id" : ObjectId("5d3ac7b8b4d620841817e7fe"), "num" : 961 } { "_id" : ObjectId("5d3ac7b8b4d620841817e7fd"), "num" : 960 } { "_id" : ObjectId("5d3ac7b8b4d620841817e7fc"), "num" : 959 } { "_id" : ObjectId("5d3ac7b8b4d620841817e7fb"), "num" : 958 }
Other operators
operator | describe |
---|---|
$where | Execute arbitrary JavaScript to select documents |
$regex | Matching Regular Expressions |
$mod[(quatient),(result)] | Match if the dividend of the element matches the result |
$type | Matches if the element type matches the specified BSON type |
$text | Allow text search to be performed on fields that create text indexes |
null | It's not a keyword, don't add $, just look at the use |
#Demonstrate mod and regex only #Then use the numbers collection. > db.numbers.find({"num":{$mod:[200,3]}}) { "_id" : ObjectId("5d3ac7b8b4d620841817e440"), "num" : 3 } { "_id" : ObjectId("5d3ac7b8b4d620841817e508"), "num" : 203 } { "_id" : ObjectId("5d3ac7b8b4d620841817e5d0"), "num" : 403 } { "_id" : ObjectId("5d3ac7b8b4d620841817e698"), "num" : 603 } { "_id" : ObjectId("5d3ac7b8b4d620841817e760"), "num" : 803 } #Search for all documents whose username begins with p using the user set just now > db.user.find({"username":{$regex:/^p.*/}}) { "_id" : ObjectId("5d3ab322b4d620841817e43c"), "username" : "pjjlt3", "age" : 18 } #The use of null to search for documents that do not have this domain, or that domain is null > db.user.find({"username":null}) > db.user.find({"username111":null}) { "_id" : ObjectId("5d3ab322b4d620841817e43c"), "username" : "pjjlt3", "age" : 18 }
aggregate operation
The aggregation framework can be understood as GROUP BY in SQL. In order to invoke the aggregation framework, you need to define a pipeline. Each step output in the aggregation pipeline serves as the next input. Similar to the concept of flow.
operator | describe |
---|---|
$project | Specify the fields (items) in the output document |
$match | Select the fields to process, similar to find(). |
$limit | Limit the number of documents passed to the next step |
$skip | Skip a certain number of documents |
$unwind | Expand the array to generate an output document for each array entry |
$group | Grouping documents by key |
$skip | Sort documents |
$geoNear | Select documents near a geographical location |
$out | Write the results of the pipeline into a collection |
$redact | Control access to specific data |
Many of the above commands have the same functions as the query commands above, & dollar; geoNear (which seems interesting, similar to those algorithms in graph theory such as Dijster Stella and Freud, which can calculate the physical distance between coordinate points) and & dollar; redact have not been discussed much at first. & dollar; limit, & dollar; skip, & dollar; skip is too simple, as demonstrated above, and will not be repeated here. Take a look at the analogy between these commands and relational database SQL
SQL command | Aggregate Command Operator |
---|---|
SELECT | $project $group functions : $sum,$min,$avg,etc. |
FROM | db.collectionName.aggregate(...) |
JOIN | $unwind |
WHERE | $match |
GROUP BY | $group |
HAVING | $match |
But the set command operator does not have to be written in the above order. For example, you can write $match for conditional filtering and then do other operations (in fact, it is often recommended to do so, after all, the first step is to filter most of the useless data).
#For illustration, create a new collection > db.score.find() { "_id" : ObjectId("5d3bac2d78b22e869eb2fd26"), "name" : "pjjlt", "age" : 25, "city" : "sjz" } { "_id" : ObjectId("5d3bac5878b22e869eb2fd27"), "name" : "qex", "age" : 112, "city" : "london" } { "_id" : ObjectId("5d3bad9078b22e869eb2fd28"), "name" : "haha", "age" : 24, "city" : "sjz" } { "_id" : ObjectId("5d3bada078b22e869eb2fd29"), "name" : "heihei", "age" : 25, "city" : "bj" } #Verify $match and $project > db.score.aggregate([ ... {$match:{age:{$lt:100}}}, //Conditional filtration ... {$project:{"_id":0}} //Do not display primary keys ... ]) { "name" : "pjjlt", "age" : 25, "city" : "sjz" } { "name" : "haha", "age" : 24, "city" : "sjz" } { "name" : "heihei", "age" : 25, "city" : "bj" } #The next group shows the average age of each city. > db.score.aggregate([ {$group:{_id:"$city",avgAge:{$avg:"$age"}}} ]) { "_id" : "bj", "avgAge" : 25 } { "_id" : "london", "avgAge" : 112 } { "_id" : "sjz", "avgAge" : 24.5 }
For $ group, for raw data such as city and age, we need to add $, such as $ city, $ age before displaying, otherwise it will be null.
Also show commands that can be used in $group
command | describe |
---|---|
$addToSet | Create an array of unique values in a group |
$first | The first value in the group makes sense only with the prefix $sort |
$last | The last value in the group, only the prefix $sort, makes sense |
$max | Maximum value of a field in a group |
$min | Minimum value of a field in a group |
$avg | Average value of a field |
$push | Returns an array of all values in the group. No duplicate values |
$sum | Find the sum of all values in a group |
#Come back and show the $out character, and the $out character is similar to the stream collector in Java 8 and must be last executed. > db.score.aggregate([ {$group:{_id:"$city",avgAge:{$avg:"$age"}}} ,{$out:'aResult'}]) #Delete the data in the variable > db.aResult.find() { "_id" : "bj", "avgAge" : 25 } { "_id" : "london", "avgAge" : 112 } { "_id" : "sjz", "avgAge" : 24.5 } #Finally, $unwind, followed by the last tools Collection > db.tools.find() { "_id" : ObjectId("5d3ad78eb4d620841817e825"), "tools" : [ "AAA", "BBB", "CCC", "DDD", "EEE" ], "city" : "SJZ" } > db.tools.aggregate([ ... {$project:{"_id":0}}, ... {$unwind:"$tools"} ... ]) { "tools" : "AAA", "city" : "SJZ" } { "tools" : "BBB", "city" : "SJZ" } { "tools" : "CCC", "city" : "SJZ" } { "tools" : "DDD", "city" : "SJZ" } { "tools" : "EEE", "city" : "SJZ" }
Like relational databases, data can be further processed when project ing. Optional functions include concat, toLower, toUpper string functions, add, mod, multiply arithmetic functions, date operators, logical operators, set operators, etc. There will be time to sum up later.
Atomicity
mongo is not as good at transaction processing as mysql. For example, when two different threads update (+1 operation), data may be overwritten. In particular, we introduce an atomic operation findAndModify(), which always finds that the modification submission is an atomic event, during which other threads will be rejected to query the data.
Of course, in order to protect data, lock can be considered at the business code level (such as java).
> db.score.find({"name":"qex"}) { "_id" : ObjectId("5d3bac5878b22e869eb2fd27"), "name" : "qex", "age" : 112, "city" : "london" } #Age of modifying qex > db.score.findAndModify({ ... query:{"name":"qex"}, ... update:{ $inc:{"age":+3}} ... }) { "_id" : ObjectId("5d3bac5878b22e869eb2fd27"), "name" : "qex", "age" : 112, "city" : "london" } > db.score.find({"name":"qex"}) { "_id" : ObjectId("5d3bac5878b22e869eb2fd27"), "name" : "qex", "age" : 115, "city" : "london" }
Summarize the update operators
Operator | describe |
---|---|
$inc | Change numbers based on given values |
$set | Set the field to the given value |
$unset | Cancel Settings Field |
$rename | Rename the value given by the field |
$setOnInsert | In upsert, set fields when inserting |
$bit | Perform bitwise update fields only |
$ | Locate subdocuments to be updated according to the query selector |
$push | Add values to arrays |
$addToSet | Add values to arrays, repeat and do not process |
$pop | Delete the first or last value from the array |
$pull | Delete the value matching the query condition from the array |
$pullAll | Delete multiple values from an array |
$each | Use it together from push and addToSet to manipulate multiple values |
$slice | Use push with each other to reduce the size of the updated array |
$sort | Use push with each and slice to sort subdocuments in an array |
$isolated | Isolate other operations and do not allow other operations to cross-update multiple documents |
Indexes
Index classification
- unique index
Make sure that there is only one copy of the data in the set, such as the primary key, format:
> db.user.createIndex({username:1},{unique:true}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
- Sparse Index
Sparse indexing ensures that some documents do not contain this attribute and will not be filtered out. For example, building an index by phone number, but the number of documents in the collection is null, so these documents will not be taken into account when creating the index.
> db.user.createIndex({username:1},{sparse:true})
- Multi-key index
The index field is a number, such as the tools field in the tools collection, which means that queries on the index for any value of these arrays will be located on the document.
- Hash indices
The advantage of hash indexing is that entries on the index are evenly distributed.
db.user.createIndex({username:'hashed'})
- Geographical Location Index
Query documents near a location and store each document based on latitude and longitude.
Of course, the number of reference fields can also be divided into single-key index and composite index, similar to the behavior of mysql.
Index Management
- Indexing
Use createIndex(). Since the amount of data will cause the system to wait for a long time when indexing, it is possible to specify the background index (because a lot of data is needed, I did not experiment), and lead away from the clue, etc.
db.user.createIndex({username:'hashed'},{background: true})
Repeated index manipulation can generate large amounts of fragmentation in memory, and commands can be used to defragment (index newly created)
> db.user.reIndex() { "nIndexesWas" : 2, "nIndexes" : 2, "indexes" : [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "pjjlt.user" }, { "v" : 2, "unique" : true, "key" : { "username" : 1 }, "name" : "username_1", "ns" : "pjjlt.user" } ], "ok" : 1 }
- View Index
To view the index of a collection, use getIndexes()
> db.user.getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "pjjlt.user" }, { "v" : 2, "unique" : true, "key" : { "username" : 1 }, "name" : "username_1", "ns" : "pjjlt.user" } ]
- Delete index
> db.user.dropIndex("username_1") #Names can be found when looking at the index { "nIndexesWas" : 2, "ok" : 1 }
engine
There are two main types: MMAPV1 and WiredTiger. Before version 2.6, only MMAPV1 was available. After version 3.0, there was WiredTiger, but by default it was still MMAPV1. This article uses version 4, which is the Wired Tiger engine by default. WiredTiger uses much less disk space than MMAPV1, requiring nearly one-seventh or eighth of that space. Remember to upgrade from the old version of mongo, import data, the original 20G data only last a single digit (a few specific G forgotten), startled, but also worried about losing data, the original engine changed. At the same time, the granularity of the lock is from database to document level, and the concurrency performance is improved a lot. In short, the new engine takes up less resources and has higher performance.
Reproduction and fragmentation
Replication: Replication is a method of distributing and maintaining data across multiple Mongo servers (nodes). MongoDB replicates data from one node to another and synchronizes changes. This type of replication is provided through a mechanism called a replicable set. The nodes in the cluster are configured to automatically synchronize data and to automatically tolerate disaster in the server. MongDB also has an old replication method: master-slave replication. Generally, when replicating data, when the data is synchronized to most of the nodes (more than 50%, for example, two of the three machines), the replication operation can be considered complete. The replicable set should protect at least three members, one of which can be a referee.
Fragmentation: Fragmentation is the process of partitioning large data sets into smaller manageable fragments. Simply put, a MongoDB server can't hold or process so much data (1, 2, 3, 4, 5, 6), so it divides the data into three smaller machines and maintains (1, 4) (2, 5) (3, 6) separately.
Reference resources
MongoDB Actual Warfare
Newbie Course https://www.runoob.com/mongod...