I have this code inside my php:
$m = new MongoClient();
$db = $m->selectDB('authentication');
$collection = new MongoCollection($db, 'digits');
$document = array(
"username" => $_POST['username'],
"digits" => $_POST['digits']
);
$collection->insert($document);
I want these documents to be deleted after 2 hours automatically using ttl feature of mongodb.
there may be thousands of documents inserting every minute, so I don't want them to get messy or buggy, I want them to be deleted independently in the same collection.
If you can put the code in php I'd appreciate it. because everywhere else they just explained mongodb commands directly, which I couldn't understand how to use it in php. thanks.
Edit 1:
with the help of "Christian P", I created 30 documents for test:
for($i=0;$i<30;$i++){
$m = new MongoClient();
$db = $m->selectDB('authentication');
$collection = new MongoCollection($db, 'teeeest');
$collection->ensureIndex(array('createdAt' => 1, 'expireAfterSeconds' => 60));
$document = array(
"username" => "4563678678",
"digits" => "5958974",
"createdAt" => new MongoDate()
);
$collection->insert($document);
sleep(1);
}
but they are not being removed.
an example of created documents:
{
"_id": {
"$oid": "53ac7c237fae31100e000109"
},
"username": "4563678678",
"digits": "5958974",
"createdAt": {
"$date": "2014-06-26T20:01:39.000Z"
}
}
{
"_id": {
"$oid": "53ac7c247fae31100e00010a"
},
"username": "4563678678",
"digits": "5958974",
"createdAt": {
"$date": "2014-06-26T20:01:40.000Z"
}
}
{
"_id": {
"$oid": "53ac7c257fae31100e00010b"
},
"username": "4563678678",
"digits": "5958974",
"createdAt": {
"$date": "2014-06-26T20:01:41.000Z"
}
}
Edit 2:
as "Christian P" said in his edit, "expireAfterSeconds" should be passed as an array.
To automatically expire data from collection by setting TTL you must do two things:
Create a Date field.
Create a TTL index on that field.
To create a Date field in PHP you need to use MongoDate object:
$document = [
"username" => $_POST['username'],
"digits" => $_POST['digits'],
"createdAt" => new MongoDate()
];
You can add a TTL index using ensureIndex command, as other regular indexes.
$collection->ensureIndex(
['createdAt' => 1], ['expireAfterSeconds' => 7200]
);
The above command will add an index TTL index on the createdAt that will delete documents after 2 hours.
Related
I am using the PHP MongoDB\Driver\Manager and I want to query by creating a MongoDB\Driver\Query.
So I have the following collection design:
{
"_comment": "Board",
"_id": "3",
"player": "42",
"moves": [{
"_id": "1",
"piece": "b3rw4",
"from_pos": "E2",
"to_pos": "E4"
}]
}
How can i query this collection to receive, for all boards of a specific player all moves with min(id)? This means I first want to filter all boards, to get only boards with player ID. Then I want to search all those board's "moves" fields, where I want the min(_id) of that "moves" field.
I currently have this query:
$filter = ['player' => '93'];
$options = [
'projection' => ['_id' => 0,
'moves' => 1]
];
$query = new MongoDB\Driver\Query($filter, $options);
This results in finding all "moves" arrays by Player 93.
How can I then filter all those "moves" fields by only getting the moves with min(_id)?
Ok, so I figured it out. I simply had to use an aggregation pipeline.
Here is the shell command which gives the expected output:
db.boards.aggregate( [
{
$match: {'player': '93'}
},
{
$unwind: {path: '$moves'}
},
{
$group:
{
_id: '$_id',
first_move: { $min: '$moves._id' },
from_pos : { $first: '$moves.from_pos' },
to_pos: { $first: '$moves.to_pos' }
}
}
])
Here is the corresponding PHP MongoDB code using Command and aggregate:
$command = new MongoDB\Driver\Command([
'aggregate' => 'boards',
'pipeline' => [
['$match' => ['player' => '93']],
['$unwind' => '$moves'],
['$group' => ['_id' => '$_id',
'firstMove' => ['$min' => '$moves._id'],
'from_pos' => ['$first' => '$moves.from_pos'],
'to_pos' => ['$first' => '$moves.to_pos']
]
]
],
'cursor' => new stdClass,
]);
$manager = new MongoDB\Driver\Manager($url);
$cursor = $manager->executeCommand('db', $command);
I'm trying to build a faceted search using Elasticsearch-php 6.0, but I'm having a hard time to figure out how to use a date range aggregation. Here's what I'm trying to do :
Mapping sample :
"mappings": {
"_doc": {
"properties": {
...
"timeframe": {
"properties": {
"gte": {
"type": "date",
"format": "yyyy"
},
"lte": {
"type": "date",
"format": "yyyy"
}
}
}
...
In my document, I have this property:
"timeframe":[{"gte":"1701","lte":"1800"}]
I want to be able display a facet with a date range slider, where the user can input a range (min value - max value). Ideally, those min-max values should be returned by the Elasticsearch aggregation automatically given the current query.
Here's the aggregation I'm trying to write in "pseudo code", to give you an idea:
"aggs": {
"date_range": {
"field": "timeframe",
"format": "yyyy",
"ranges": [{
"from": min(timeframe.gte),
"to": max(timeframe.lte)
}]
}
}
I think I need to use Date Range aggregation, min/max aggregation, and pipeline aggregations, but the more I read about them, the more I'm confused. I can't find how to glue this whole world together.
Keep in mind I can change the mapping and / or the document structure if this is not the correct way to achieve this.
Thanks !
As for me with the official "elasticsearch/elasticsearch" package of ES itself, I was able to find a range of my required documents with this document.
You need to read the documentation as you'll be needing the format.
$from_date = '2018-03-08T17:58:03Z';
$to_date = '2018-04-08T17:58:03Z';
$params = [
'index' => 'your_index',
'type' => 'your_type',
'body' => [
'query' => [
'range' => [
'my_date_field' => [
//gte = great than or equal, lte = less than or equal
'gte' => $from_date,
// 'lte' => $to_date,
'format' => "yyyy-MM-dd||yyyy-MM-dd'T'HH:mm:ss'Z'",
'boost' => 2.0
]
]
],
]
];
$search = $client->search($params);
I'm trying to update an array stored in mongo, but I'm getting this error cannot use the part (data of data.info) to traverse the element. I've tried lot of things and read many other posts but none fits my problem and isn't there enough documentation about how to reach using PHP with the new driver.
I need to add a document inside the array of documents called info.
This is what I'm doing in PHP:
$conn = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$bulk = new MongoDB\Driver\BulkWrite;
$options = ["upsert" => true];
$document = ['$push' => ["data.info" => ["user" => "Megan", "hours" => [12, 13]]]];
$filtro = ["year" => 2016, "month" => 5, "day" => 18, "data.room" => 1];
$bulk->update($filtro, $document, $options);
$aux = $conn->executeBulkWrite("prueba.books3", $bulk);
Data that I have stored:
{
"_id":ObjectId("571a0eb07d67f0b82324e683"),
"year":2016,
"month":5,
"day":18,
"data":[
{
"room":1,
"info":[
{
"user":"Jack",
"hours":[
10,
11,
16
]
}
]
}
]
}
Example of how it should look after the update:
{
"_id":ObjectId("571a0eb07d67f0b82324e683"),
"year":2016,
"month":5,
"day":18,
"data":[
{
"room":1,
"info":[
{
"user":"Jack",
"hours":[
10,
11,
16
]
},
{
"user":"Megan",
"hours":[
12,
13
]
}
]
}
]
}
I have a collection named requests with documents following this prototype:
{
"_id": {
"$id": "56295368ef2b8e5458000029"
},
"title": "Hardcoded Name",
"requestorId": "dve34gegrgeefdsfewe"
}
The requestorId of those documents correlates with the id (not the _id Mongo Object ID) of the users collection, whose documents follow this prototype:
{
"_id": {
"$id": "86235288ef2gif5458000027"
},
"id": "dve34gegrgeefdsfewe",
"name": "John Doe"
}
I need to be able to run a find() on the requests collection and obtain the name associated with the requestorId in each request document. I would normally just do the obvious: run a find() on requests, then while looping through each document, do a subsequent query on users where id = [requestorId (really "id" in users collection)], BUT I need to be able to sort the entire requests collection by the name associated with each requestorId, then use skip() & limit(). This should be pretty simple but I can't seem to figure it out... Here's my code so far, inspired by https://www.noppanit.com/merge-documents-two-collections-together-mongodb/
$m = new MongoClient(); // connect
$db = $m->{"database"};
// construct map and reduce functions
$eventRequest_map = new MongoCode("function() {
emit(this.requestorId, {\"requestorId\" : this.requestorId})
}");
$user_map = new MongoCode("function() {
emit(this.id, {\"name\" : this.name})
}");
$reductionFunction = new MongoCode("function(key, values) {
var result = {
\"requestorId\" : \"\",
\"name\" : \"\"
};
return result;
}");
$sales = $db->command(array(
'mapreduce' => "requests",
'map' => $eventRequest_map,
'reduce' => $reductionFunction,
'query' => array(),
'out' => 'joined'));
$sales = $db->command(array(
'mapreduce' => "users",
'map' => $user_map,
'reduce' => $reductionFunction,
'query' => array(),
'out' => 'joined'));
$collection = $db->joined;
$cursor = $collection->find();
$outputJoined = array();
foreach($cursor as $doc){
$outputJoined[] = $doc;
}
echo json_encode($outputJoined);
In my mongodb collection I want to push some elements to an existing array. I use jenssegers/Laravel-MongoDB - Eloquent model and Query builder to work with lavavel and mongodb.
How can I use the $push operator in jenssegers/Laravel-MongoDB?
MongoDB entry which shall be updated (RockMongo representation):
{
"_id": ObjectId("5328bc2627784fdb1a6cd398"),
"comments": {
"0": {
"id": 3,
"score": 8
}
},
"created_at": ISODate("2014-03-18T21:35:34.0Z"),
"file": {
"file_id": NumberLong(1175),
"timestamp": NumberLong(1395178534)
}
}
Hint about array representation in rockmongo and mongo shell
RockMongo and mongo shell array representation of the documents are a little bit different. Have a look at the comments-array. The above RockMongo representation appears in the mongo shell as:
{
"_id" : ObjectId("5328c33a27784f3b096cd39b"),
"comments" : [
{
"id" : 3,
"score" : 8
}
],
"created_at" : ISODate("2014-03-18T22:05:46Z"),
"file" : {
"file_id" : NumberLong(1176),
"timestamp" : NumberLong(1395180346)
}
}
As the documentation states the $push operater to push elements to an array. This works fine in the mongo-shell:
Mongo shell
db.Images.update({'file.file_id': 1175},
{ $push: { comments: { id: 3, score: 8} }
})
But in the query-builder I struggle to incorporate the $push operator. I get the error:
localhost:27017: Modified field name may not start with $
I did not find any documentation or example that showed me how to do it..
My jenssegers/Laravel-MongoDB code, that returns the error
// $file_id = 1175
public static function addComment( $file_id ) {
$image = Images::where( 'file.file_id', '=', floatval( $file_id ) )
->update( array('$push' => array( 'comments' => array( 'id' => 4, 'score' => 9 ) ) ) );
return $image;
}
Assuming everything is okay as it works in the shell then use the provided method to push instead:
Images::where('file.file_id', '=', floatval( $file_id ))
->push('comments', array( 'id' => 4, 'score' => 9 ));