Hi I am MySQL user and new to mongoDB.
I get data from my IOT devices as following:
$body={
"key": "121239",
"secrete": "Your_Device_Secrete",
"data": [
{
"Temperature":50,
"Humidity":30,
"Vibration":100,
"Time":"2020-1-26 00:00:01"
},
{
"Temperature":55,
"Humidity":34,
"Vibration":50,
"Time":"2020-1-26 00:00:02"
}
]
}
I am inserting it into mongoDB using PHP CodeIgnitor as following:
$this->mongo->batch_insert($body["key"],$body["data"]);
data is getting inserted in collection named as given key as following:
{
"Temperature": 50,
"Humidity": 30,
"Vibration": 100,
"Time": "2020-1-26 00:00:01",
"_id": {
"$id": "5e330be3f7577f640d2a0922"
}
},
{
"Temperature": 55,
"Humidity": 34,
"Vibration": 50,
"Time": "2020-1-26 00:00:02",
"_id": {
"$id": "5e330be3f7577f640d2a0923"
}
}
Now I want to add timestamp to every row getting inserted. I want data getting inserted as following :
{
"Temperature": 50,
"Humidity": 30,
"Vibration": 100,
"Time": "2020-1-26 00:00:01",
"_id": {
"$id": "5e330be3f7577f640d2a0922"
},
timestamp:<CURRUNT TIME>
},
{
"Temperature": 55,
"Humidity": 34,
"Vibration": 50,
"Time": "2020-1-26 00:00:02",
"_id": {
"$id": "5e330be3f7577f640d2a0923"
},
timestamp:<CURRUNT TIME>
}
is there any way to make mongoDB add current timestamp auto like MySQL?
First of all you should not store date/time values as string! It will just generate trouble at later times. Better use
"Time": ISODate("2020-01-26T00:00:02Z")
"Time": new Date("2020-01-26 00:00:02") may also work
Then in general you don't need to insert a timestamp. Every document gets an internal _id identifier which contains also the time when it was inserted. You can try like this:
db.collection.aggregate([
{
$project: {
timestamp: {
$toDate: "$_id"
},
key: 1,
secrete: 1,
data: 1,
_id: 0
}
}
])
Result:
{
"data": [
{
"Humidity": 30,
"Temperature": 50,
"Time": "2018-02-26 01:00:00",
"Vibration": 100
},
{
"Humidity": 34,
"Temperature": 55,
"Time": "2018-02-26 01:00:00",
"Vibration": 50
}
],
"key": "121239",
"secrete": "Your_Device_Secrete",
"timestamp": ISODate("2018-02-26T00:00:00Z")
}
You can also query for it, e.g.
db.collection.find({
$expr: {
$gte: [ {"$toDate": "$_id"}, ISODate("2020-01-03T11:00:00Z") ]
}
})
However, if you like to insert timestamp explicitly then simply do it like this.
{
"Temperature": 50,
"Humidity": 30,
"Vibration": 100,
"_id": {
"$id": "5e330be3f7577f640d2a0923"
},
"timestamp": new Date()
}
Or "timestamp": ISODate() should also work
Another note, this embedded document "_id": {"$id": "5e330be3f7577f640d2a0923"} looks really strange. I assume this is a bug. The string look like a ObjectId object used for _id. Somehow you scratched it.
Update
I really recommend to use proper data types. In PHP the insert could look like this:
$mongo->db->collection->insertOne([
"timestamp" => new MongoDB\BSON\UTCDateTime(NULL),
"key" => "121239",
"secrete" => "Your_Device_Secrete",
"data" => [
[
"Temperature" => 50,
"Humidity" => 30,
"Vibration" => 100,
"Time" => new MongoDB\BSON\UTCDateTime(new DateTime("2020-1-26 00:00:01"))
],
[
"Temperature" => 55,
"Humidity" => 34,
"Vibration" => 50,
"Time" => new MongoDB\BSON\UTCDateTime(new DateTime("2020-1-26 00:00:02"))
]
]
]);
I also had similar requirements as yours while reading sensor values from DHT11 sensor in my IoT class. I was able to insert all the temperature and humidity readings into MongoDB but later while plotting the graph I realized that I would need the timestamps as well. After researching for a while, I came up with this query. However, it will create a new collection in the database.
Here, the new collection name is dht11-sensor-readings.
Please also refer to https://docs.mongodb.com/manual/reference/operator/aggregation/out/ for more.
db.collection.aggregate([
{
$addFields:{timestamp:{$toDate:"$_id"}
}
},
{ $out:"dht11-sensor-readings"
}
])
Related
I currently have the below json response that the API is returning. I am able to return it using Laravel Eloquent. There are several users and each user has a several receipts. A receipt has types and status. I want to try to get the total sum amount for each receipt that is related to its type and status. I was able to return the below json response using
$this->user->with('receipts')->has('receipts')->get(['id', 'name']);
I have tried using multiple laravel collections methods https://laravel.com/docs/5.8/collections#available-methods
But I am still unable to get the desired response.
{
"id": 1,
"name": "kent",
"receipts": [
{
"id": 1,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 2,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 3,
"user_id": 1,
"type_id": 2,
"status": 1,
"amount": 50
},
{
"id": 4,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 5,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 6,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 20
},
{
"id": 7,
"user_id": 1,
"type_id": 1,
"status": 1,
"amount": 10
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"id": 9,
"user_id": 2,
"type_id": 1,
"status": 0,
"amount": 20
}
]
}
]
I expect to get the below
{
"id": 1,
"name": "kent",
"receipts": [
{
"performance and deleted": 220,
"performance and not deleted": 10,
"project and deleted": 60,
"project and deleted": 50
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"performance and deleted": 20,
"performance and not deleted": 0,
"project and deleted": 0,
"project and not deleted": 0
}
]
}
]
You should be able to get the sum of amount with
$this->user->with(['receipts' => function($query) {
$query->selectRaw("SUM(amount) as amount, type_id, status, user_id")->groupBy('type_id', 'status', 'user_id');
}])->has('receipts')->get(['id', 'name']);
You can use collection methods to get the desired output
$this->user->with(['receipts' => function($query) {
$query->selectRaw("SUM(amount) as amount, type_id, status, user_id")->groupBy('type_id', 'status', 'user_id');
}])->has('receipts')->get(['id', 'name'])
->each(function ($user) {
$user->setRelation(
'receipts',
$user->receipts->mapWithKeys(function ($receipt) {
return [
$receipt->type_id . ' and ' . $receipt->status => $receipt->amount // format the key as you wish
];
})
);
})
You may use foreach and other loops to make the json you want!
use This function to convert your collection to the json you want :
public function convert(Collection $collection)
{
$result_collection = $collection;
$payment_collections = [];
foreach ($result_collection->receipts as $receipt)
{
$payment["type_id${receipt->type_id} and status${$receipt->status}"] = $receipt->amount;
}
$result_collection->receipts = $payment_collections;
return $result_collection;
}
And This is same way to get total amount. Just put an foreach and add each amount to a variable that initialized with 0;
and there is other ways like change toArray function in your Resource Collection.
I wrote the script assuming your data is a PHP array so you may change some part of my code.
For example you may change:
$row['receipts']
// To
$row->receipts
anyway
// The function in your controller
function index(){
$users=User::whereHas('receipts')->with('receipts')->get()->toArray();
return convert($users);
}
// The helper function
function convert($data){
$data=collect($data);
$allTypes=[];
$allStatuses=[];
return $data->each(function($row) use (&$allTypes,&$allStatuses){
$types=collect($row['receipts'])->pluck('type_id')->toArray();
$statuses=collect($row['receipts'])->pluck('status')->toArray();
$allTypes=array_unique(array_merge($allTypes,$types));
$allStatuses=array_unique(array_merge($allStatuses,$statuses));
})->map(function ($row,$index) use (&$allTypes,&$allStatuses){
$result=[];
$receipts=collect($row['receipts']);
foreach ($allTypes as $type){
foreach ($allStatuses as $status){
$result["type_id {$type} and status {$status}: "]=$receipts->where('type_id',$type)->where('status',$status)->sum('amount');
}
}
$row['receipts']=$result;
return $row;
});
}
I want to store product option on my database and loop through it when I retrieve the data. The data structure takes a form
[
{
"color": "black",
"extralCost": 100,
"size": {
"xs": 1,
"sm": 4,
"L": 2,
"XL":6
},
"stock":13
}, {
"color": "white",
"extralCost": 0,
"size": {
"xs": 1,
"sm": 4,
"L": 2
},
"stock":7
},
...
]
I want to be able to store this in the database and retrieve it at the view.
Add this to your Model.
protected $casts = [
'column_name' => 'array',
];
To get an array:
$request->except('_token', '_method')
I am trying to get data from elastic search in PHP.
Following is my elastic type (curated) structure :
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "qwerty",
"_type": "curated",
"_id": "2",
"_score": 1,
"_source": {
"shows_on_lfz": [
{
"sh_id": 14,
"sh_parent_id": 102,
"sh_name": "Veg Versions Of Global Dishes"
}
]
}
},
{
"_index": "qwerty",
"_type": "curated",
"_id": "1",
"_score": 1,
"_source": {
"top_stories": [
{
"ts_id": 515,
"ts_parent_id": 485,
}
]
}
}
]
}
}
How can I get all data of top_stories using search query in PHP?
I am getting data using match_all & get() query but I need data using search().
I tried -
$body['query']['bool']['should'] = ['match' => ['top_stories'=> '']];
But getting a null response.
This is the query that will bring all entries that have the field top_stories
GET qwerty/_search
{
"query": {
"exists": {
"field": "top_stories"
}
}
}
You can convert this to code and you can test it through kibana
This question already has an answer here:
How to limit contained associations per record/group?
(1 answer)
Closed 6 years ago.
Hii i am new to cakephp 3.2 v.
Here i have used model association (hasMany).
Here in bind section (campaign_videos) ,i want to fetch only one record ,
so for this ,i have put below code to manage it.
my actual data in db.
[
{
"id": 1,
"user_id": 95,
"campaign_videos": [
{
"id": 1,
"campaign_id": 1,
},
{
"id": 3,
"campaign_id": 1,
}
]
},
{
"id": 2,
"user_id": 95,
"campaign_videos": [
{
"id": 2,
"campaign_id": 2,
}
]
},
$fetchCampaignFirst = $this->Campaigns->find()->contain(['CampaignVideos' => ['queryBuilder' => function ($q) {
return $q->limit(1);
}]]);
I am getting this limit working for first data only ,not for others (others even not showing the fetched data).
Below i have written the output
Here i want to get an output like
[
{
"id": 1,
"user_id": 95,
"campaign_videos": [
{
"id": 1,
"campaign_id": 1,
},
]
},
{
"id": 2,
"user_id": 95,
"campaign_videos": [
{
"id": 2,
"campaign_id": 2,
}
]
}]
Only want the first record of campaign_videos.
Here after using the queryBuilder query , i am getting out put like.
[
{
"id": 1,
"user_id": 95,
"campaign_videos": [
{
"id": 1,
"campaign_id": 1,
},
]
},
{
"id": 2,
"user_id": 95,
"campaign_videos": [
]
}]
I am not getting any data for second id ,while data is present for it.
Please suggest me.
Thank you in advance.
Maybe I'm wrong (so feel free to downvote my answer) but I think it's not feasible using a simple query
in fact cake, when loading associated data, does a single query on the associated table and after that matches the rows with the corresponding ones in the main table.
So you would need to do a mysql query that find the first record of every category. i.e. something like what is described in this article
I think that the only (or maybe the simpler) solution is to loop through your records:
$campaigns= $this->Campaigns->find();
foreach($campaigns as $campaign)
{
$campaign->campaign_videos = $this->Campaigns->CampaignVideos-find()
->where(['campaign_id' => $campaign->id]
->order(['id' => 'asc'])
->limit(1);
}
This question already has an answer here:
How to limit contained associations per record/group?
(1 answer)
Closed 6 years ago.
Hii i am new to cakephp 3.2 v.
Here i have used model association (hasMany).
Here in bind section (campaign_videos) ,i want to fetch only one record ,
so for this ,i have put below code to manage it.
my actual data in db.
[
{
"id": 1,
"user_id": 95,
"campaign_videos": [
{
"id": 1,
"campaign_id": 1,
},
{
"id": 3,
"campaign_id": 1,
}
]
},
{
"id": 2,
"user_id": 95,
"campaign_videos": [
{
"id": 2,
"campaign_id": 2,
}
]
},
$fetchCampaignFirst = $this->Campaigns->find()->contain(['CampaignVideos' => ['queryBuilder' => function ($q) {
return $q->limit(1);
}]]);
I am getting this limit working for first data only ,not for others (others even not showing the fetched data).
Below i have written the output
Here i want to get an output like
[
{
"id": 1,
"user_id": 95,
"campaign_videos": [
{
"id": 1,
"campaign_id": 1,
},
]
},
{
"id": 2,
"user_id": 95,
"campaign_videos": [
{
"id": 2,
"campaign_id": 2,
}
]
}]
Only want the first record of campaign_videos.
Here after using the queryBuilder query , i am getting out put like.
[
{
"id": 1,
"user_id": 95,
"campaign_videos": [
{
"id": 1,
"campaign_id": 1,
},
]
},
{
"id": 2,
"user_id": 95,
"campaign_videos": [
]
}]
I am not getting any data for second id ,while data is present for it.
Please suggest me.
Thank you in advance.
Maybe I'm wrong (so feel free to downvote my answer) but I think it's not feasible using a simple query
in fact cake, when loading associated data, does a single query on the associated table and after that matches the rows with the corresponding ones in the main table.
So you would need to do a mysql query that find the first record of every category. i.e. something like what is described in this article
I think that the only (or maybe the simpler) solution is to loop through your records:
$campaigns= $this->Campaigns->find();
foreach($campaigns as $campaign)
{
$campaign->campaign_videos = $this->Campaigns->CampaignVideos-find()
->where(['campaign_id' => $campaign->id]
->order(['id' => 'asc'])
->limit(1);
}