How to store float value in MongoDB - mongodb

I'm using jenssegers/laravel-mongodb package (for Laravel) and I'm trying to store float values in database so I can order them but it always stores them as string. I tried using $casts attribute and I tried direct casting like $some_value = (float)$value; but it doesn't work.
Is it possible to cast the attribute while calling orderBy function, in other words, is it possible to trick Eloquent so it orders the rows as float, not as string (I attempted to fix this with mutators but still no progress).
EDIT:
This is the mutator that I use. It works ok for "int" part, but when it's float then the rate is converted to string.
I tried converting everything to float but it didn't help
public function setRateAttribute($value)
{
if(strpos($value, ".") !== false or is_float($value)) {
$this->attributes['rate'] = (float)$value;
} else {
$this->attributes['rate'] = (int)$value;
}
}
EDIT2:
$c = new \App\Contractor();
$c->rate = "1.5";
$c->save();
This is example from php artisan tinker, it's the same in application only with additional fields.
The problem is that some entries are converted to float but some are string. I can't reproduce it always, it happens randomly.
This is example response when I loop through all entries and var_dump only rate:
string(5) "16.67"
string(5) "33.33"
string(5) "24.44"
string(5) "33.33"
string(5) "33.33"
string(5) "27.78"
string(5) "27.78"
string(4) "8.89"
string(4) "6.67"
string(5) "22.22"
string(5) "16.67"
int(0)
float(1.5)
float(1.5)

MongoDB doesn't support float directly; it has double instead, so you can use
$some_value = (double)$value;
and you need to make sure the syntax is correct.

Related

Dereference a ReferenceField in Mongoengine

I am trying to dereference a reference field on my Flask backend and return the complete object with that certain field dereferenced.
The field I am trying to dereference is defined like this:
vouches_received = db.ListField(db.ReferenceField('Vouch'))
The way I am trying to dereference it is like this:
unverified_vouches = []
for vouch in usr.vouches_received:
unverified_vouches.append(vouch.to_mongo())
usr.vouches_received = unverified_vouches
However, when I then do:
usr.to_json()
On the object, then I get a ValidationError like so:
ValidationError: u'{...}' is not a valid ObjectId, it must be a
12-byte input of type 'str' or a 24-character hex string
The 3 dots (...) is basically the document dereferenced, it has mostly Strings, a Date Field, and some other reference fields I do not wish to dereference.
I am aware this is a valid error, as it is expecting an ObjectID for the reference field, but then arises the question, how do I succeed at dereferencing that field and return the document.
Thanks
The ListField is expecting elements of ObjectId and because you've de-referenced them it throws that error. I'm not sure this is the most elegant way but could you convert the usr.to_json() to a dict and then replace the vouches_received list with a deferenced list afterwards - I can't test it but something like?
user_dict = json.loads(usr.to_json())
unverified_vouches = []
for vouch in usr.vouches_received:
user_dict['vouches_received'].append(vouch.to_mongo())
usr_json = json.dumps(user_dict)
A better solution may be to use an EmbededDocument.

Impresspages Data Grid Trouble

I am a data grid implemented in the Impresspages admin environment. The form has date fields. The problem is the following. Entered date is storage in Mysql (and logically returned too) like 000-00-00. I caught the public function createData($postData) from one field in the grid and the content is correct, the fields value are right. Let's see:
array(12) {
["securityToken"]=> string(32) "b9d273d7f6f17a43eacb61a008543d21"
["antispam"]=> array(2) { [0]=> string(0) "" [1]=> string(32)
"692a03a931157644de8a0986ebfa54ea" }
["active"]=> string(1) "1"
["starSign"]=> string(2) "22"
["startPeriod"]=> string(10) "2015-04-25"
["endPeriod"]=> string(10) "2015-04-25"
["prevLove"]=> string(25) "dsdsds"
["prevHealth"]=> string(25) "asasas"
["prevBiz"]=> string(27) "lklklklk"
["prevLucky"]=> string(27) "fgfgfgfg"
["languageId"]=> string(1) "2"
["createdAt"]=> string(19) "2015-04-22 14:02:37"
}
Look at the fields startPeriod and EndPeriod. In the data array they are set up to real values typed: 2015-04-22, However it is stored in the DB the weird value 0000-00-00. Any idea, please? Thanks.
Check the camelCase issue. Maybe in your database those fields are not in the same upper/lower case. This is the issue if you migrate your database between windows/unix. Make user that your config is exactly the same and you don't have any mistype.
you get 0000-00-00 on MySQL field when you provide incorrect value or you don't provide any value and the field is set as NOT NULL.
I personally never got such issue with Date field.

Morphia MongoDB check for null and non existing field

I am new to both Morphia and MongoDB. Is there a way to check using Morphia that a certain field in my database is not null and also exists. For example from the following record of a user from a collection of users in database:
{ "_id" : ObjectId("51398e6e30044a944cc23e2e"),
"age" : 21 ,
"createdDate" : ISODate("2013-03-08T07:08:30.168Z"),
"name" : "Some name" }
How would I use a Morphia query to check if field "createdDate" is not null and exists.
EDIT:
I am looking for a solution in Morphia. So far I have come up with this:
query.and(query.criteria("createdDate").exists(),
query.criteria("createdDate").notEqual(null));
From documentation, I learnt Morphia does not store empty or null fields. Hence the justification for notEqual(null).
EDIT 2: From the answers I can see the problem needs more explanation. I cannot modify the createdDate. To elaborate: the example above is less complex than my actual problem. My real problem has sensitive fields which I cannot modify. Also to complicate things a bit more, I do not have control over the model otherwise I could have used #PrePersist as proposed in one of the answers.
Is there a way to check for null and non existing field when I have no control over the model and I am not allowed to modify fields?
From the documentation, Morphia does not store Null/Empty values (by default) so the query
query.and(
query.criteria("createdDate").exists(),
query.criteria("createdDate").notEqual(null)
);
will not work since it seems you are not able to query on null, but can query for a specific value.
However, since you can only query for a specific value, you can devise a workaround where you can update the createdDate field with a date value that is never used in your model. For example, if you initialize a Date object with 0, it will be set to the beginning of the epoch, Jan 1st 1970 00:00:00 UTC. The hours you get is the localized time offset. It will be sufficient if your update only involves modifying the matching element(s) in mongo shell, hence it would look similarly to this:
db.users.update(
{"createdDate": null },
{ "$set": {"createdDate": new Date(0)} }
)
You can then use the Fluent Interface to query on that specific value:
Query<User> query = mongoDataStore
.find(User.class)
.field("createdDate").exists()
.field("createdDate").hasThisOne(new Date(0));
It would be much simpler when defining your model to include a prePersist method that updates the createdDate field. The method is tagged with the #PrePersist annotation so that the date is set on the order prior to it being saved. Equivalent annotations exist for #PostPersist, #PreLoad and #PostLoad.
#Entity(value="users", noClassNameStored = true)
public class User {
// Properties
private Date createdDate;
...
// Getters and setters
..
#PrePersist
public void prePersist() {
this.createdDate = (createdDate == null) ? new Date() : createdDate;
}
}
When you first create your Morphia instance, before calling morphia.mapPackage() do this:
morphia.getMapper().getOptions().setStoreNulls(true);
to have Morphia store null values.
Anyway, you should be able to query non-null values with:
query.field("createdDate").notEqual(null);
In mongo you can use this query:
db.MyCollection.find({"myField" : {$ne : null}})
This query will return objects that have the field 'myField' and has a value that is not null.

How to get result by joining two collections (tables) [Cakephp/MongoDB]

I am using https://github.com/ichikaway/cakephp-mongodb.git plugin for accessing mongodb datasource.
I have two Models: Teachers and Subject. I want joint find result on Teacher and Subject.
Here are my two models:
Teacher:
<?php
class Teacher extends AppModel {
public $actsAs = array('Containable');
public $hasOne = array('Subject');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'string'),
'age'=>array('type'=>'string'),
'subjectid'=>array('type'=>'string'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime'),
);
Subject:
<?php
class Subject extends Model {
public $actsAs = array('Containable');
public $belongsTo= array('Teacher');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'String'),
'code'=>array('type'=>'String'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime')
);
In Teachers Controller to get joint result, I did:
$results = $this->Teacher->find('all',array('contain'=>array('Subject')));
$this->set('results', $results);
But I am not getting any result from Subjects Collections.
Here is what I am getting:
array(5) {
[0]=>
array(1) {
["Teacher"]=>
array(7) {
["_id"]=>
string(24) "52e63d98aca7b9ca2f09d869"
["name"]=>
string(13) "Jon Doe"
["age"]=>
string(2) "51"
["subjectid"]=>
string(24) "52e63c0faca7b9272c09d869"
["modified"]=>
object(MongoDate)#78 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
["created"]=>
object(MongoDate)#79 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
}
}
I am a cakephp/mongoDB rookie only, Please guide me to get the desired result.
Edit: I read that mongoDb don't support Join Operation. Then How to manually do it? I mean I can write two find query on each Model, then how to combine both array and set it to view?
As you said, MongoDB does not support joins. Documents in query results come directly from the collection being queried.
In this case, I imagine you would query for Teacher documents and then iterate over all documents and query for the Subject documents by the subjectid field, storing the resulting subject document in a new property on the Teacher. I'm not familiar with this CakePHP module, but you may or may not need to wrap the subjectid string value in a MongoId object before querying. This depends on whether or not your document _id fields in MongoDB are ObjectIds or plain strings.
If Subjects only belong to a single teacher and you find that you never query for Subjects outside of the context of a Teacher, you may want to consider embedding the Subject instead of simply storing its identifier. That would remove the need to query for Subjects after the fact.

How to get metadata result set using zend

How to get metadata from query result,.?
I wanna get the datatype of each column from my query result,.
singles linked to a helpful post in his comment, but more specifically, here is how you can get the data type for a column from your table.
// $tbl is your Zend_Db_Table object
$info = $tbl->info(Zend_Db_Table_Abstract::METADATA); // get the table metadata, fetches it if it is not yet set
// get the data type for the "email_address" column
$type = $info['email_address']['DATA_TYPE']);
For each column in your table, you will have an array of data like so:
["column_name"] =>
array(14) {
["SCHEMA_NAME"]=> NULL
["TABLE_NAME"]=> string(8) "accounts"
["COLUMN_NAME"]=> string(10) "account_id"
["COLUMN_POSITION"]=> int(1)
["DATA_TYPE"]=> string(9) "mediumint"
["DEFAULT"]=> NULL
["NULLABLE"]=> bool(false)
["LENGTH"]=> NULL
["SCALE"]=> NULL
["PRECISION"]=> NULL
["UNSIGNED"]=> bool(true)
["PRIMARY"]=> bool(true)
["PRIMARY_POSITION"]=> int(1)
["IDENTITY"]=> bool(true)
}