Hello community :) I implemented lots of good working functionality with firebase -> realm. Now i tried to edit a structure and I am running through the wildest error messages.
What is right for sure:
Firebase sends the data
Data is Converted (e.g. Firebase has "brands" as array -> is converted to a string for Realm Schema)
The error appears when firebase updates
Not every firebase content has all fields (e.g. Like you can see out of Realm Schema some fields are optional: true)
Fields where i maybe expect an issue:
Maybe its not possible to say that the ReferentList is optional (or i implemented it wrong): See Realm Schema const ReferentsList
What i tried
Debug before realm.create (Realm set) Result: Every data came in the right format
Checked all input values if they are int, string, ...
Hopefully someone can help me here because i got completely stuck with this issue and its necesarry to continue for my project. I want to know:
The solution why or what to do
A posibility to debug realm in a better way
Thank you in advance for your time and help :)
Error message: Value not convertible to a number
Firebase datastructure
"begin" : "2017-05-15T15:50:00.000Z",
"description" : "abc",
"end" : "2017-05-15T16:15:00.000Z",
"id" : 6,
"language" : [ 1 ],
"location" : "L 1.02",
"member" : 20,
"referent" : [ 1, 3 ],
"register" : true,
"title" : "Sound of Silence",
"track" : 6,
"type" : 3,
"brands" : [ 1, 2, 3 ]
Realm Schema
const ReferentListSchema = {
name: 'ReferentList',
properties: {
id: {
type: 'int',
optional: true
}
}
}
const LanguageListSchema = {
name: 'LanguageList',
properties: {
id: 'int'
}
}
const EventSchema = {
name: 'Events',
primaryKey: 'id',
properties: {
id: 'int',
begin: {
type: 'date',
optional: true
},
end: {
type: 'date',
optional: true
},
title: 'string',
description: 'string',
register: 'bool',
member: {
type: 'int',
optional: true
},
language: {
type: 'list',
objectType: 'LanguageList'
},
location: 'string',
referent: {
type: 'list',
objectType: 'ReferentList'
},
type: 'int',
track: {
type: 'int',
optional: true
},
img: {
type: 'string',
optional: true
},
brands:{
type: 'string',
optional: true
}
}
}
Realm set
set(obj) {
realm.write(() => {
if(obj.referent){
obj.referent = obj.referent.map(function(id) {
return {id};
})
}
if (obj.language){
obj.language = obj.language.map(function(id) {
return {id};
})
}
realm.create('Events', obj, true);
});
}
Solved:!
The issue got solved through wrong data at firebase. Some Date Objects hasent been set correct.
How i got to the solution
When i tried to debugg the code i made a try/catch block around:
try{
realm.create('Events', obj, true);
}catch(error){
console.log(obj);
console.log(error);
}
Through this debug i found the right data wich was wrong. Before it just showed me all objects and afterwards the error.
I wont close this question because of the chance to help someone with the same issues.-
Related
After spent 1 day trying to get things done, I think it's time to ask for help.
I want to populate 2 levels of a document.
I tried with populate() but it seems to work only for first level, not deep populate! I read a lot at SO and I know it should work but I think I'm missing something really stupid...
Please let me know where I'm making mistakes.
Here are the relevant code.
Schemas
var compositionSchema = new Schema({
name: {
type: String,
required: true
},
contributions: [{
type: Schema.Types.ObjectId,
ref: 'Contribution'
}]
});
mongoose.model('Composition', compositionSchema);
var contributionSchema = new Schema({
name: {
type: String,
required: true
},
media: {
type: Schema.Types.ObjectId,
ref: 'Media'
}
});
mongoose.model('Contribution', contributionSchema);
var mediaSchema = new Schema({
name: {
type: String,
required: true
}
});
mongoose.model('Media', mediaSchema);
Actual documents saved in MongoDB
compositions:
{
"_id" : ObjectId("59e5db4595fe650a71fb0e07"),
"name" : "Test Pop 7",
"contributions" : [
ObjectId("59e5db4595fe650a71fb0e05")
]
}
contributions:
{
"_id" : ObjectId("59e5db4595fe650a71fb0e05"),
"name" : "Honda",
"media" : ObjectId("59e4ac5dacacd709eac2c856")
}
media:
{
"_id" : ObjectId("59e4ac5dacacd709eac2c856"),
"name" : "Logo_big.png",
"width" : 662,
"height" : 540
}
My tries (= the wrong code?)
In Node JS, when I do this (as per documentation):
Composition.findOne({ name: "Test Pop 7" })
.populate({
path: 'contributions',
model: 'Contribution',
populate: {
path: 'media',
model: 'Media',
}
})
.exec((error, doc) => {
if (error) { console.log(error); }
else {
console.log(doc);
}
});
prints out this, without actually populate the media field:
{ _id: 59e5db4595fe650a71fb0e07,
name: 'Test Pop 7',
contributions:
[ { _id: 59e5db4595fe650a71fb0e05,
name: 'Honda',
media: [Object] } ]
}
It works, keeping in mind the key-word in your question: prints. Printed, with console.log(), it just shows you the type (checked with typeof) of the document included in an array for some (2nd) level of nesting. If you do:
console.log(doc.contributions[0].media[0])
you will see your populated media document.
So I've been at this for awhile and can't see how my code is different from the documentation.
I've also checked out this question, this question, this question, and this unanswered different question.
For my admin panel I'm trying to query to get all the information associated with a user and display a 'master' user profile to the admin.
My User model looks like this:
module.exports = {
autoPK: true,
attributes : {
id: {
type: 'integer',
primaryKey: true,
unique: true
},
email : {
type : 'email',
unique : true,
required : true,
},
password : {
type : 'string',
minLength : 8,
required : true
},
admin:{
type: 'bool'
},
user_profile:{
collection: 'userprofile',
via: 'user_id',
},
properties: {
collection: 'subjectproperties',
via: 'user_id'
},
employment_info: {
collection: 'employmentinfo',
via: 'user_id'
},
file_uploads: {
collection: 'fileupload',
via: 'user_id'
},
nearest_living_relatives:{
collection: 'nearestlivingrelative',
via: 'user_id'
},
mortgage_info: {
collection: 'mortgageinfo',
via: 'user_id'
},
user_progression_state:{
collection: 'userprogressionstate',
via: 'user_id'
},
users_applied_loan_values:{
collection: 'usersappliedloanvalues',
via: 'user_id'
}
}
}
I don't want to list out all the belongs to user models cause there are a lot of them, but here is one of the simpler one's.
EmploymentInfo.js
module.exports = {
tableName: "employment_info",
attributes : {
employers_name:{
type: 'string',
required: true
},
employers_address:{
type: 'string',
required: true
},
employers_city:{
type: 'string',
required: true
},
employers_state:{
type: 'string',
required: true
},
employers_zip:{
type: 'string',
required: true
},
job_position:{
type: 'string',
required: true
},
years_in_position:{
type: 'string',
required: true
},
years_in_industry:{
type: 'integer',
required: true
},
user_id:{
model:'user'
}
}
};
And as for my controller:
create_admin_user_profile: function(req, res){
var user_id = req.query.userId;
User.find({'id': user_id}).populateAll().exec(function(err, user){
if(err || user.length === 0){
sails.log.verbose(err);
}else{
sails.log.verbose(user);
}
});
},
It doesn't error out but all I see in the terminal is this for the above:
[ { user_profile: [],
properties: [],
employment_info: [],
file_uploads: [],
nearest_living_relatives: [],
mortgage_info: [],
user_progression_state: [],
users_applied_loan_values: [],
id: 5,
email: 'test#test.com',
admin: 1 } ]
Even though there is an entry in all of those tables for that user.
If I change the line:
User.find({'id': user_id}).populateAll().exec(function(err, user){
To:
User.find({'id': user_id}).populate('employment_info').exec(function(err, user){
Same but shorter result:
[ { employment_info: [],
id: 5,
email: 'test#test.com',
admin: 1 } ]
I've tried changing the case, I've tried adding columnName to the user_id attribute, I've tried changing the column name across the entire breadth of the project to not have an under_score in it, though that never seemed to be issue in it picking up the names correctly, but nothing I've done seems to work. I've also tried uninstalling sails, and the sails-mysql adapter and clearing my npm cache.
At this point my just stuck, I really can't see a reason why it's not working.
As for project info:
Sails v: 0.12.11
npm v: 3.10.9
node v: 7.2.0
Additional info asked for in comments:
SQL row taken right from db for user 5
employers_name, employers_address, employers_city, employers_state, employers_zip, job_position, years_in_position, years_in_industry, user_id
'Company', 'Mill Steet', 'SLC', 'Utah', '88888', 'Developer', '2', '2', '5'
And json format returned by find method in EmploymentInfo.js controller
{
"employmentInfo": {
"employers_name": "Company",
"employers_address": "Mill Steet",
"employers_city": "SLC",
"employers_state": "Utah",
"employers_zip": "88888",
"job_position": "Developer",
"years_in_position": "2",
"years_in_industry": 2,
"user": 5
}
}
The reason the last param is user and not user_id is because I rename it in the find method to serve the front-end mvc which also has the ability to work with associations. It's also why the JSON has the format it does.
Code from the find method that replaces user_id:
EmploymentInfo.find({'user_id': user_id}).exec(function(err, profile){
if(err || !profile.length){
return res.json(err);
}else{
res.status(200);
profile[0].user = profile[0].user_id;
delete profile[0].user_id;
res.send({'employmentInfo': profile[0]});
}
});
However I've tried not renaming it; I've also tried getting rid of my find override and just relying on the blueprint find method, neither of those worked either.
I wrote an app using Sails.js with mongoDb(sails-mongo).
Firstly, I decided to write all to a single document...
And database slowed on 5GB of data..
"Slowed" means that basic find query executed in 30-50s..
Than I rewrite all in an multiple collections and add indexing..
example of my models:
Markets.js
module.exports = {
attributes: {
name: {
type: 'string',
index: true
},
pairs: {
collection: 'Exchanges',
via: 'source',
}
}
};
and Exchanges.js
module.exports = {
attributes: {
s1: {
type: "string"
},
source:{
model: "Maklers",
index: true
},
s2: {
type: "string"
},
p: {
type: 'float'
},
v1: {
type: 'float'
},
v2: {
type: 'float'
},
vb: {
type: 'float'
}
}
};
and example of slow query
Markets.findOne({
name: info,
sort: 'createdAt DESC',
limit: 1,
createdAt: {
'<=': aft
}
}).populateAll().exec(function(err, items) {
callback(err, items);
});
result of db.stats
> db.stats()
{
"db" : "stats222",
"collections" : 8,
"objects" : 36620661,
"avgObjSize" : 238.26556139988844,
"dataSize" : 8725442352,
"storageSize" : 10033258480,
"numExtents" : 63,
"indexes" : 13,
"indexSize" : 2940024192,
"fileSize" : 14958985216,
"nsSizeMB" : 16,
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"dataFileVersion" : {
"major" : 4,
"minor" : 22
},
"ok" : 1
}
What you can advice me?
It`s about 2000 of records every minute..
How to increase perfomance?
Change db config? Change indexes? Change DB? Change models/collections config?
I using 2-core server with 2GB of Virtual Memory..
Sorry for bad english..
There is a drawback in the 0.12 version of Waterline when using mongodb. By default waterline is not case sensitive, and mongodb is!
Your queries are slow, because when searching strings, it is being used a REGEX to find any case, so your indexes are useless. But you can change it, by disabling the case sensitiveness with the wlnex attribute:
someMongodbServer: {
adapter: 'sails-mongo',
host: 'mongodb',
port: 27017,
user: 'username',
password: 'password',
database: 'databaseCoolName',
wlNext: {
caseSensitive: true
}
},
You can confirm this error by checking on the mongodb logs. And see what are the slow queries.
I am working in a Sencha Touch app and with associated models
Parent model:
Ext.define('xx.model.TemplateModel', {
extend : 'Ext.data.Model',
requires : [
'xx.model.BrandsModel'
],
config : {
useCache : false,
idProperty: 'templates',
fields : [
{
name: 'id',
type: 'string'
},
{
name: 'name',
type: 'string'
},
{
name: 'validFrom',
type: 'auto'
},
{
name: 'validTo',
type: 'auto'
}
]
},
associations: [
{
type : 'hasMany',
associatedModel: 'xx.model.BrandsModel',
ownerModel : 'xx.model.TemplateModel',
autoLoad : true,
associationKey : 'brands'
}
]
});
and associated model:
Ext.define('xx.model.BrandsModel', {
extend : 'Ext.data.Model',
requires: [],
config : {
useCache : false,
idProperty: 'Brands',
fields : [
{
name: 'brandId',
type: 'string'
},
{
name: 'brandText',
type: 'string'
}
]
}
});
First point, this implementation is in the correct way?, because I cannot see this associated model when I am debugging in the chrome console.
Second point, What would it be the correct way to test this and to see the records?
Thank you.
I would have expected that it throws an error:
You have no "brands" field on your template model, but have specified the associationKey to be brands
You have not specified a primaryKey on the association although you use a modified idProperty on the BrandsModel
Also, please have a look at the example in the API docs how to lessen your code by using readable shortcuts.
I'm running into an issue with beforeValidate(), and can't find any answers online. My model has two relationship attributes that require id numbers in POSTed data. If a user POST strings instead, they get a validation error. I want to enable the user to POST string data, then inside beforeValidate() use findOrCreate() to find or create the attribute's related model, then overwrite the POSTed data's attribute with the relate model's ID.
I have the following model:
attributes: {
reporter : { model: 'reporter', required: true },
location : { model: 'location', required: true },
line : { type: 'boolean', required: true, defaultsTo: true },
count : { type: 'int', required: true, defaultsTo: 0},
composition : { type: 'int', required: true, defaultsTo: 3}
},
beforeValidate: function(values, next) {
if (typeof values.reporter !== 'number') {
Reporter.findOrCreate({name: values.reporter}).exec(function(data){
console.log(data)
values.reporter = data.id;
})
};
next();
},
I'm POSTing this data to the model's create() default blueprint endpoint:
{
"location":"Harry's",
"reporter":"tim",
"count":30,
"composition":3,
"line":false
}
When I log the above values inside beforeValidate(), I get this:
{ location: NaN,
reporter: NaN,
count: '30',
composition: '3',
line: false }
When I replace "location" and "reporter" with ID's, I don't get any errors. Why are the string values getting stripped out in the beforeValidate() function?
maybe u need POST(create) to endpoint location model, then POST(create) to reporter model, and then POST YOUMODEL/id/reporterID, POST YOUMODEL/id/location ID