deleting records mongo db in collection - mongodb

How can I use below script for deleting 5K records:
db.transaction.deleteMany({
"timeStamp": { $gte: new Date(2018, 0, 1), $lt: new Date(2019, 0, 1) }
})
I tried with finding first in collection, but it's saying 0 records fetched.
db.transaction.find({
"timeStamp": { $gte: new Date(2018, 0, 1), $lt: new Date(2019, 0, 1) }
})
Output: Fetched 0 record(s) in 31ms
But i checked in collection below records with these timestamp are present,
"timeStamp" : ISODate("2018-12-31T18:30:03.379Z"),
"timeStamp" : ISODate("2018-12-31T18:30:03.982Z"),

Related

Find document range same day from mongodb use GetMongo processor by NiFi

I want to get the documents in mongodb for the day. I tried querying with mongo compass the code works. The code is as follows:
{
"time_created": {
"$gte": new Date(new Date().setHours(0, 0, 0, 0)),
"$lt": new Date(new Date().setHours(23, 59, 59, 999))
}
}
But when I use the above query code with the "query" property of GetMongo, I get the following error message:
Verification Results
Perform Validation
Component is invalid: 'Query' validated against '{ "time_created": { "$gte": new Date(new Date().setHours(0, 0, 0, 0)), "$lt": new Date(new Date().setHours(23, 59, 59, 999)) } }' is invalid because Query is not a valid JSON representation due to Unrecognized token 'new': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false') at [Source: (String)"{ "time_created": { "$gte": new Date(new Date().setHours(0, 0, 0, 0)), "$lt": new Date(new Date().setHours(23, 59, 59, 999)) } }"; line: 3, column: 16]
I tried converting to JSON format but it doesn't work:
{
"time_created": {
"$gte": { "$date": "${now():format('yyyy-MM-dd\'T\'HH:mm:ss.SSS\'Z\'')}" },
"$lt": { "$date": "${now():format('yyyy-MM-dd\'T\'23:59:59.999\'Z\'')}" }
}
}
and
{
"time_created": {
"$gte": "${now():toDate():format('yyyy-MM-dd\'T\'HH:mm:ss.SSS\'Z\'')}",
}
}
but it not work.
Please help me, thanks.
Can you help me convert mongodb query to json format working with GetMongo ?
{
"time_created": {
"$gte": new Date(new Date().setHours(0, 0, 0, 0)),
"$lt": new Date(new Date().setHours(23, 59, 59, 999))
}
}
Give me another more suitable solution ?
Please help me, thanks.
I fixed it. Nifi's getMongo Query field doesnt support EL. So i created a stored function in MongoDB for my dynamic query and called it from Nifi.
Create function in Mongodb:
db.system.js.insertOne({
_id: "find_data_by_date_range",
value : function(created_time) {
var fromDate = new Date(new Date().setHours(0, 0, 0, 0));
var toDate = new Date(new Date().setHours(23, 59, 59, 999));
if ((created_time >= fromDate) && (created_time <= toDate)) {
return true;
}
return false;
}
});
Query Nifi:
{"$where": "find_data_by_date_range(this.time_created)"}
It is worked!

mongodb sum aggregation return float instead of integer

I have a document which history embedded field is as below:
first_pn_data = {'_cls': 'InstallationEmbeddedHistory',
'coverage': 0.8197712971965834,
'date': datetime.datetime(2020, 9, 7, 0, 0),
'estimated_installs': 39349022,
'popularity_rank': 0,
'rank': 1851}
second_pn_data = {'_cls': 'InstallationEmbeddedHistory',
'coverage': 0.8197712971965834,
'date': datetime.datetime(2020, 9, 7, 0, 0),
'estimated_installs': 23412618,
'popularity_rank': 0,}
The estimated_installs field is an integer.
when I run the following query:
query = [
{
"$match": {
"package_name": {
"$in": ["first_pn", "second_pn"]
}
}
},
{
"$unwind": "$history"
},
{
"$group": {
"_id": "$history.date",
"total": {
"$sum": "$history.estimated_installs"
}
}
}
]
the result for the above date is:
{'_id': datetime.datetime(2020, 9, 7, 0, 0), 'total': 62761640.54968266}
while I expect the total=62761640.
I don't know why the result is float and has a decimal.
Can someone help me with this?

Mongo 3.2 query timeseries value at specific time

I have some timeseries data stored in Mongo with one document per account, like so:
{
"account_number": 123,
"times": [
datetime(2017, 1, 2, 12, 34, 56),
datetime(2017, 3, 4, 17, 18, 19),
datetime(2017, 3, 11, 0, 1, 11),
]
"values": [
1,
10,
9001,
]
}
So, to be clear in the above representation account 123 has a value of 1 from 2017-01-02 12:34:56 until it changes to 10 on 2017-03-04 17:18:19, which then changes to 9001 at 2017-03-11, 00:01:11.
There are many accounts and each account's data is all different (could be at different times and could have more or fewer value changes than other accounts).
I'd like to query for each users value at a given time, e.g. "What was each users value at 2017-01-30 02:03:04? Would return 1 for the above account as it was set to 1 before the given time and did not change until after the given time.
It looks like $zip would be useful but thats only available in Mongo 3.4 and I'm using 3.2 and have no plans to upgrade soon.
Edit:
I can get a small part of the way there using:
> db.account_data.aggregate([{$unwind: '$times'}, {$unwind: '$values'}])
which returns something like:
{"account_number": 123, "times": datetime(2017, 1, 2, 12, 34, 56), "values": 1},
{"account_number": 123, "times": datetime(2017, 1, 2, 12, 34, 56), "values": 10},
#...
which isn't quite right as it is returning the cross product of times/values
This is possible using only 3.2 features. I tested with the Mingo library
var mingo = require('mingo')
var data = [{
"account_number": 123,
"times": [
new Date("2017-01-02T12:34:56"),
new Date("2017-03-04T17:18:19"),
new Date("2017-03-11T00:01:11")
],
"values": [1, 10, 9001]
}]
var maxDate = new Date("2017-01-30T02:03:04")
// 1. filter dates down to those less or equal to the maxDate
// 2. take the size of the filtered date array
// 3. subtract 1 from the size to get the index of the corresponding value
// 4. lookup the value by index in the "values" array into new "valueAtDate" field
// 5. project the extra fields
var result = mingo.aggregate(data, [{
$project: {
valueAtDate: {
$arrayElemAt: [
"$values",
{ $subtract: [ { $size: { $filter: { input: "$times", as: "time", cond: { $lte: [ "$$time", maxDate ] }} } }, 1 ] }
]
},
values: 1,
times: 1
}
}])
console.log(result)
// Outputs
[ { valueAtDate: 1,
values: [ 1, 10, 9001 ],
times:
[ 2017-01-02T12:34:56.000Z,
2017-03-04T17:18:19.000Z,
2017-03-11T00:01:11.000Z ] } ]
Not sure how to do the same with MongoDb 3.2, however from 3.4 you can do the following query:
db.test.aggregate([
{
$project:
{
index: { $indexOfArray: [ "$times", "2017,3,11,0,1,11" ] },
values: true
}
},
{
$project: {
resultValue: { $arrayElemAt: [ "$values", "$index" ] }
}
}])

How to increment all the array elements from position a to b in mongodb?

Suppose I have this document i mongodb.
{ "_id" : 1, "seats" : [ 80, 85, 90, 95 ] }
{ "_id" : 2, "seats" : [ 88, 90, 92, 97 ] },
{ "_id" : 3, "seats" : [ 85, 100, 90, 85 ] },
I want to increment the seats array from position 1 to position 3 of the "_id": 1 and make it to "seats": [80,86, 91, 96]. How to achieve this ?
You can try a combination of both the $inc update operator and the dot notation to access the elements of the seats array by the zero-based index position and increment them by one. The following update() operation uses the $inc operator to increase the seats array from position 1 to position 3 of the "_id": 1 field by 1:
db.collection.update(
{ "_id": 1 },
{
"$inc": {
"seats.1": 1,
"seats.2": 1,
"seats.3": 1
}
}
);
To update each element in the seats array from given index you need to loop over each element for that index and use the $inc operator to increment the value with "bulk" operation.
var bulkOp = db.collection.initializeOrderedBulkOp();
var fromIndex = 1
var toIndex = 3
db.collection.find({ '_id': 1 }).forEach(function(doc) {
var seats = doc.seats;
for(var index = fromIndex; index <= toIndex; index++) {
bulkOp.find({ '_id': doc._id, 'seats': seats[index] })
.updateOne({ '$inc': { 'seats.$':1 } });
bulkOp.execute();
Then db.collection.find({ '_id': 1 }) yields
{ "_id" : 1, "seats" : [ 80, 86, 91, 96 ] }

MongoDB find Query comparision with CurrentDate

I want to fetch current day documents from a MongoDB collection. My documents look like this:
{
"_id" : ObjectId("55743941789a9abe7f4af3fd"),
"msisdn" : "9xxxxxxxxxx",
"act_date" : ISODate("2014-11-24T00:00:00Z"),
"date" : ISODate("2015-06-07T00:00:00Z"),
"recharge" : { "recharge_amt" : 0, "rechargetype" : "WEB" },
"voice" : { "local_og_mou" : 20, "local_other_mobile_og_mou" : 0, "nld_og_mou" : 0, "nld_other_mobile_og_mou" : 10 },
"gprs" : { "total_access_count" : 1, "total_datavolume_mb" : 42 },
"sms" : { "freesms" : 3, "local_sms_count" : 0, "nat_sms_count" : 0, "inter_sms_count" : 0 }
}
As per your question you want to fetch current day documents from a mongodb collection. In mongoDB shell when you type new Date() it gives you current date with time and this value always vary when you run same new Date() so probably your query like this :
db.collectionName.find({"start_date":new Date()}).pretty()
But, I think this query return the those documents which will presents in your collection but same current Date value may be not presents in your documents SO this case you should use following
db.collectionName.find({"start_date":{"$lte":new Date()}}).pretty()
Or
db.collectionName.find({"start_date":{"$gte":new Date()}}).pretty()
In some case If you want to find exact match with year,month,day then you should use aggregation with $year,$month,$dayOfMonth in $project like this :
db.collectionName.aggregate({
"$project": {
"year": {
"$year": "$date"
},
"month": {
"$month": "$date"
},
"day": {
"$dayOfMonth": "$date"
}
}
}, {
"$match": {
"year": new Date().getFullYear(),
"month": new Date().getMonth() + 1, //because January starts with 0
"day": new Date().getDate()
}
})
In above aggregation query will return those documents which match current date like year,month,day of current date. Also you replace $match as
var currentDate = new Date()
{
"$match": {
"year": currentDate.getFullYear(),
"month": currentDate.getMonth() + 1, //because January starts with 0
"day": currentDate.getDate()
}
}
If you are using Mongoose you can include timeStamp: true after your schema definition to get autogenerated createdAt and updatedAt fields, Mongoose will take care of it.
const itemSchema = mongoose.Schema({
// Your Schema definition here
}, {
timestamps: true
})
In your case, you need to compare your TimeStamp key with the start of today which is 12 AM with ISO string as 2019-11-08T00:00:00.000Z and end of the day which is 11:59 PM with ISO string as 2019-11-08T23:59:59.999Z.
The below code will do it for you.
let queryObj = {}
const startOfDay = new Date(new Date().setUTCHours(0, 0, 0, 0)).toISOString()
const endOfDay = new Date(new Date().setUTCHours(23, 59, 59, 999)).toISOString()
queryObj.createdAt = {
$gte: startOfDay, // 2019-11-08T00:00:00.000Z
$lt: endOfDay // 2019-11-08T23:59:59.999Z
}
let items = item.find(obj)
// new Date().setUTCHours(0, 0, 0, 0) Generates this weird string '1573171200000' which is not a human readable format of TimeStamp
// To convert it into ISO String we have .toISOString() method
You can do this using below query.
db.collection.find({"start_date" : { $gte : new ISODate("2015-05-27T00:00:00Z") }});
Note : above query will return documents which are greather than specified date.
To find a date that equals another date
db.collection.find({"start_date" : new ISODate("2015-05-27T00:00:00Z") });