{ _id: ObjectId id: string operation: string time: ISODate data: { info: string result: string message: string } array: [a1, a2, ... ,aN] }
db.test.count({ "operation": "test", "time": {$gte: new Date(new Date() - 1000*60*5)} })
db.test.ensureIndex( {time: 1}, {background: true} )
. Then MongoDB will only look at the data for the last 5 minutes, and not all documents in the collection. You can add several more indices at once, but if there are too many of them, for each insert
operation, the binary trees corresponding to them will be appended, which creates additional load. And at some point, the indexes may not fit in the RAM, then reading will occur from the disk, which will significantly slow down data access.new Date()
in the time field of an insert operation, the date will be written in ISODate format. Entering the new Date()
command in the mongo shell console will display the current date in the format ISODate("YYYY-MM-DDThh:mm:ss[.sss]Z")
- you can take this line and substitute it in the query like:db.test.find({ time: {$gte: ISODate("YYYY-MM-DDThh:mm:ss[.sss]"), $lte: ISODate("YYYY-MM-DDThh:mm:ss[.sss]")} })
, where $gte
is greater than or equal to, $lte
is less than or equal to, [.sss]
is the number of milliseconds.new Date()
:db.test.find({ time: {$gte: new Date(YYYY, MM, DD, hh, mm, ss, sss) } })
, where the months count (MM) starts at 0.db.test.find({ time: {$gte: new Date( new Date() -1000*300 ) } })
- display documents in the last 5 minutes. Instead of the expression "-1000*300"
you can substitute any time in milliseconds. Also, before the request, you can pre-define variables with dates: var today = new Date(); var yesterday = new Date(); yesterday.setDate(today.getDate() - 1); db.test.find( {"time": {$gte : yesterday, $lt : today} } );
for (var i = today.getTime(); i < yesterday.getTime(); i=i+300*1000) {var b=0; b = db.test.find({ "time": { $gte: new Date(i), $lte: new Date(i+300*1000) } // getTime POSIX }).count(); // .count() time=new Date(i); // i print(b+"; "+time.toTimeString().split(' ')[0]) } // (b) + time timeString, split(' ')[0] .
.forEach()
method helps, which is applied to the cursor and is able to modify the document in an arbitrary way using javascript.id
for a specified period of time (take the last 5 minutes): db.test.aggregate({$match:{time:{$gte:new Date(new Date()-1000*300)}}}).forEach( function(doc) { print( doc.id ) } )
aggregate
in this case, you can use find
or distinct
- the main thing is that the input forEach()
an array. Since the format of the aggregation output somewhat changed from version to version, in version 2.6, for example, you should use aggregate({...},...,{...}).result.forEach
, since the output has the format "result":[{...},...,{...}]
.id
and unload into the table. db.cbh.aggregate( {$match: {time: {$gte: new Date(new Date()-1000*300)}}}, // {$group: { _id: "$id", // id "count": {$sum:1}, // id "result": {$push:"$data.result"} // } }, {$match: { "count": 4 }}, // id 4 {$match: { "result": { $ne:[] }}} // result ).result.forEach(function(doc) {print( doc._id+", "+doc.result )} )
id, data.result
”, which can be imported into excel or any relational DBMS. function avgDur(operation, period) { var i=0; var sum=0; var avg=0; db.test.aggregate( { $match : { "time" : { $gte : new Date(new Date - period*1000) } } }, { $group : {_id: "$id", "operation":{$addToSet : "$operation"}, "time":{$push : "$time"}, "count":{$sum: 1} } }, { $match : {"operation": operation, "count":4 }, { $project : {_id:0, "time":1}} ).result.forEach(function(op) { dur=op.time[3]-op.time[0]; sum=sum+dur; i=i+1; }); avg=sum/i; print(avg/1000); // }
avgDur(test,300)
and check its operation. Next, save it: db.system.js.save( { _id: "avgDur", value : function(operation, period) { ... } } )
db.loadServerScripts();
and call the avgDur(test,300)
.db.loadServerScripts()
we can get an error and cannot access other functions, so we check carefully before saving.db.test.remove({...})
command, the disk space will not be freed, because this would cause severe fragmentation. In order to avoid this, MongoDB leaves all documents in place, and adds links in the gaps. Then, in order to “compress the collection”, you need to execute db.repairDatabase()
, but the command will require as much disk space as the database takes, since first, the base is copied to the new location, and only then the files of the old base are deleted.repairDatabase()
and start the server back. It is even better to set up a TTL (time-to-live) index, where the documents themselves will be deleted after a certain lifetime, for example, after 30 days. But in this case, you still have to periodically repairDatabase()
.db.dropDatabase()
executed, disk space will be guaranteed free. But db.collectioName.drop ()
, unfortunately, does not free disk space. Data is simply marked as inaccessible.cursor.next()
method applied to the cursor, you can select the necessary data sequentially.{allowDisckUse:true}
aggregation parameter helps to avoid this.$match
block we search for all documents with "data.result":"SUCCESS"
, then only the latest documents inside each id
will be "data.result":"SUCCESS"
in the selection. The mapReduce paradigm will not help here either, since at the stage of the map MongoDB passes through the collection only 1 time.id
and perform aggregation, substituting this array in $match
: ids=[]; var monthBegin = new Date(new Date().getFullYear(),new Date().getMonth()-1,1,0,0,0,0) var monthEnd = new Date(new Date().getFullYear(),new Date().getMonth(),1,0,0,0,0) // new Date(), YYYY , new Date().getFullYear(), MM new Date().getMonth() new Date().getMonth()-1 . db.test.find({time:{$gte:monthBegin, $lt:monthEnd}, "operation":"test", "data.result":"SUCCESS"}, {"_id":0, "id":1} ).forEach(function(op) { ids.push(op.id) // id }); db.test.aggregate( {$match:{"id":{$in:ids}}}, // id {...} )
db.getSiblingDB("testDb").test.find({ "time" : { $gte : new Date(monthBegin.getTime()), $lte : new Date(monthEnd.getTime()) }, "operation" : "test", "data.result" : "SUCCESS" }).addOption(DBQuery.Option.noTimeout).forEach( // noTimeout function(doc) { db.test.find({"id" : doc.id}).forEach( // id, function(row) { db.getSiblingDB("anotherDb").newTest.insert({ // id . "id" : doc.id, "time" : row.time, }); } ); } );
{id:sting, time:ISODate(...)}
. Next, we perform a simple aggregation of the new collection and get the desired result: i=0; sum=0; avg=0; db.getSiblingDB("anotherDb").newTest.aggregate( {$group:{_id:"$id", "time":{$push:"$time"}, }} ).result.forEach(function(op) { dur=op.time[op.time.length-1]-op.time[0] sum=sum+dur; i=i+1; }); print(sum/i) // .
Source: https://habr.com/ru/post/272651/
All Articles