About upsert in pymongo - mongodb

Each record in the collection has two key "ip" and "timestamp"
db.posts.update({'ip' : '127.0.0.1', 'timestamp' : {'$gt' : sometimestamp}}, {'$set' : {'timestamp' : time.time()}, True)
The command above will insert a new record, if field "ip" with "127.0.0.1" not in the collection or "timestamp" is less than sometimestamp
Now, if I want to insert a new record only "ip" with "127.0.0.1" not in collection, in other word, keep value of "ip" unique.
How to do ?

What you are probably trying to do is this:
if( ip=127)
if( ts > myts)
update;
else
DO NOTHING;
else
insert;
So essentially, you are having two different types of updates..One is going to acutally make a change in timestamp and other tells mongo to do nothing, i.e., not even make an insert.
I am guessing this is not possible with an upsert. So better use simple updates as follows:
db.posts.update ( { 'ip' : '127.0.0.1', 'timestamp' : { '$gt' : sometimestamp } } , { '$set' : { 'timestamp' : time.time() } , False)
And I don't know how you'd write it in Pymongo, but logically speaking, you do this:
if (db.posts.find_one( { 'ip':'127.0.0.1'} ) != null):
db.posts.update ( {'ip' : '127.0.0.1'}, { '$set' : {'timestamp' : time.time() } } )
Unfortunately, I can't comment on the performance..

Related

how to change a key value in mongodb when i push data with moloquent

$cart = Cart::where('user_id', $request->user_id)->push('cart', [
"uuid" => uniqid(),
"product_id" => $request->product_id,
"product_type_id" => $request->product_type_id,
"address_id" => $request->address_id,
"voucher_id" => $request->voucher_id,
"coureer_id" => $request->coureer_id,
"note" => $request->note,
"qty" => $request->qty,
"type" => $request->type,
"expired_at" => $this->addWeekFromCurrentTime(4),
"created_at" => $this->getCurrentTime()
]);
this is the result
how to change a key value in mongodb when i push data with moloquent
when i push, mongodb always generate a incremental key, how can i change it ?
You must override _id becouse MongoDB always generate default ID for your bson or if you want disable it you could create colletions without default index
db.createCollection("coll", { autoIndexId: false })
this could be done in mongo console

MongoDB Raw query to select documents which are in given datetime period

I want to select documents which are in user given date time period like between :
$from_date : "2017-01-07 09:08:59" To `$to_date : "2017-08-09 09:08:59"`
I'm using laravel framework and jenssegers/laravel-mongodb mongodb driver to run my query, And this is my Raw query :
$normal_banners = BannerView::raw(function ($collection) use ($id, $from_date, $to_date) {
$conditions = [
["camp_id" => ['$eq' => $id]],
['$or' => [
['seat_target_status' => ['$eq' => true]],
['seat_target_status' => ['$eq' => false]]
]],
['camp_target_status' => ['$eq' => false]],
];
if ($from_date) {
$conditions[] = ['created_at' => ['$gte' => $from_date]];
}
return $collection->aggregate([
['$match' => ['$and' => $conditions]],
]);
})->count();
But my problem is that it returns 0 as result; while there are 16 documents in this time period.
I've tried this method to get the count of them but still 0 result :
$normal_banners = BannerView::Where('camp_id', $id)
->where(function ($query) {$query->where('seat_target_status', true)->orWhere('seat_target_status', false);
})
->where('camp_target_status', false)
->where("created_at", ">=", $from_date)
->count();
FYI : I've converted datetime of input to ISODate Which is the mongodb datatype for created_at field.
$Fromdatetime = $request->input('from_date');
$from_date = new DateTime($Fromdatetime);
$from_date = $from_date->format(DateTime::ISO8601);
mongodb field data type is :
"updated_at": ISODate("2017-04-10T09:35:58.641Z"),
"created_at": ISODate("2017-04-10T09:35:58.641Z")
My input data type is : "2017-01-07T09:08:59+0000"
Any suggestion ?
You have to "put in braces" orWhere function and in your raw query you are testing $to_date with updated_at column, but in Eloquent code you are making between with created_at column
$targeted_banners = BannerView::Where('camp_id', $id)
->where(function($query){$query->where('seat_target_status', true)->orWhere('seat_target_status', false);})
->where('camp_target_status', false)
->where("created_at", ">=" $from_date)
->where("updated_at", "<=", $to_date)
->count();
I've solved this problem using Carbon::createDateFrom method, it create a UTC date time base on my input :
Inputs :
{
"from_date": "2017-03-10",
"to_date": "2017-04-09"
}
Converting input dates :
$from_date_arr = explode("-",$request->input('from_date'));
$from_date = Carbon::createFromDate($from_date_arr[0],$from_date_arr[1],$from_date_arr[2]);
$to_date_arr = explode("-",$request->input('to_date'));
$to_date = Carbon::createFromDate($to_date_arr[0],$to_date_arr[1],$to_date_arr[2]);
And This is the query I run which worked :
$normal_banners = BannerView::Where('camp_id', $id)
->where(function ($query) {$query->where('seat_target_status', true)->orWhere('seat_target_status', false);
})
->where('camp_target_status', false)
->where("created_at", ">=",$from_date)
->where("created_at", "<=",$to_date)
->count();
There is a strange problem still with jessenger driver which whereBetween is not working and we should use two where clause to make it work.
Hope solves others problem.

MongoDB PHP Date

In my database I have a document like this.
{
"_id" : ObjectId("5465508f453c9446d228b225"),
"category" : "animals",
"lastLocation" : "Wilpattu",
"lastSeenDate" : "2013-05-26",
"company" : "53fd9a3204ac58132377f807"
}
I want to check if the given date is in between two date ranges. I am using Codeigniter for front end development. In the model class I have written,
$connection =$this->Dbconnect->GetMongoCon();
$database = $connection->etsp;
$collection = $database->trackedObjects;
$start = $AnimalArray['fyear']. '-'.$AnimalArray['fmonth'].'-'.$AnimalArray['fday'];
$end = $AnimalArray['lyear']. '-'.$AnimalArray['lmonth'].'-'.$AnimalArray['lday'];
$searchCriteria = array(
'company' => $AnimalArray["Company"],
'lastSeenDate' =>array('$gt' => $start1, '$lte' => $end1)
);
$ReturnAnimalArray=$collection->find($searchCriteria);
But I can't query the date. From internet I have tried converting date into mongodb format.
$start1 = new MongoDate(strtotime(date($start )));
$end1 = new MongoDate(strtotime(date($end)));
But that also did not work. Any hint will be highly appreciated.
lastSeenDate is not MongodbDate format, may be you should like do this:
$js = "function() {
return this.lastSeenDate > '2013-02-18' && this.lastSeenDate <= '2014-09-28';
}";
$collection->find(array('$where' => $js));

Mongodb : find documents including references to sub-documents [node-mongodb-native]

I have the following Mongodb Documents :
Users : {'_id' : '12345', 'fullname' : 'ABC'}
and
Files :
{'_id' : 'File001', 'path' : 'pathA', 'Users_id' : '12345'}
{'_id' : 'File002', 'path' : 'pathB', 'Users_id' : '12345'}
How do i query or find all 'Files' documents in a way that the 'Users_id' which is referencing to the 'Users' document has the full 'Users' Document?
Expected Output :
{'_id' : 'File001', 'path' : 'pathA', 'Users_id' : '12345', 'user' : {'_id' : '12345', 'fullname' : 'ABC'}}
{'_id' : 'File002', 'path' : 'pathB', 'Users_id' : '12345', 'user' : {'_id' : '12345', 'fullname' : 'ABC'}}
In this way, i could access the file owner's fullname as such : file.user.fullname
I Appreciate any help from you guys. Thank you.
--- EDIT
I am using node-mongodb-native to access the db.
Below is my code to retrieve it:
var files = db.collection ('Files');
files.find ({}, {}).toArray (function ( err, filesDoc){
for ( var index in filesDoc) {
var fileDoc = filesDoc [ index ];
var users = db.collection ('Users');
users.findOne ({'_id' : fileDoc.Users_id}, {}, function (errUser, userDoc){
if ( ! errUser ) {
fileDoc.user = userDoc;
}
});
}
});
but this code is not assigning the user to all files doc and only assigns to the last element of the filesDoc array. Any suggestions?
MongoDB doesn't support joins so you have to query for the User details separately. If you're using node.js, Mongoose provides a populate feature to help simplify this so you can do something like the following to pull in the user details:
Files.find().populate('Users_id')
I managed to find the cause of the issue. The reason why my code returns a null user is because I saved File.Users_id as String and I am retrieving it using ObjectId.
I fixed my codes by converting Users_id String to ObjectId before saving the File.

Why $pull operator doesn't work on MongoDB when using empty criteria?

I have nodes like this:
[_id] => MongoId Object (
[$id] => 4e90cb3cd68417740c000017
)
[label] => mystery
[owner] => me
[parents] => Array (
[0] => Array (
[id] => MongoId Object (
[$id] => 4e8c6bb6d68417340e0004ca
)
[owner] => userid
[timestamp] => 1318112522
)
)
[timestamp] => 1318112060
[translabel] => mystery
[type] => 0
What I am trying to do is to remove parents with id : 4e8c6bb6d68417340e0004ca , wherever they are.
For example this should have been working (latest Mongo):
db.nodes.update({},{$pull : {"parents": { "id" : ObjectId("4e8c6bb6d68417340e0004ca") }}});
or equaly in PHP (latest driver etc):
$mongodb->nodes->update(array(),array('$pull'=> array('parents'=>array('id'=> new MongoId("4e8c6bb6d68417340e0004ca")))));
both don't do anything!
on the other hand:
db.nodes.update({"_id": ObjectId("4e90cb3cd68417740c000017")},{$pull : {"parents": { "id" : ObjectId("4e8c6bb6d68417340e0004ca") }}});
or equaly in PHP:
$mongodb->nodes->update(array('_id' => new MongoId("4e90cb3cd68417740c000017"),array('$pull'=> array('parents'=>array('id'=> new MongoId("4e8c6bb6d68417340e0004ca")))));
work perfectly well! Is this a bug? Is it a problem that I use "id" instead of "_id" with MongoID objects in my subdocuments? Thanks in advance for any help!
Have you tried enable multi flag on update command
db.collection.update( criteria, objNew, upsert, multi )
multi - indicates if all documents matching criteria should be updated rather than just one. Can be useful with the $ operators below.
and change your query to
db.nodes.update({},{$pull : {"parents": { "id" : ObjectId("4e8c6bb6d68417340e0004ca") }}},false,true);
or
db.nodes.update({ "_id" : { $exists : true } },{$pull : {"parents": { "id" : ObjectId("4e8c6bb6d68417340e0004ca") }}},false,true);
i haven't tested the code myself, but am sure that any one of the above will work..