I have this data on my firebase:
transportation: {
"car" : {
"bus" : {
"toyota" : false,
"bmw" : true
},
"suv" : {
"honda" : false,
"toyota" : true,
}
}
}
I want to delete all child that have "false" value data so that my data looks like this:
transportation: {
"car" : {
"bus" : {
"bmw" : true
},
"suv" : {
"toyota" : true,
}
}
}
This is code,
var ref = firebase.database().ref().child('transportation/')
ref.once("value")
.then(function(snapshot) {
data = snapshot.val();
for (var i=0;i < Object.keys(data).length;i++){
Object.keys(data)[i].forEach(function(childSnapshot) {
if(childSnapshot.val() == "false"){
childSnapshot.ref.remove();
}
});
}
}).catch(function(error) {alert("Data could not be deleted." + error);}););
In order to delete record from fairbase with its value, bellow may work:
var dB = firebase.database()
dB.ref('transportation/car').once('value', snap={
snap.forEach(s =>{
var obj =s.val();
var keys = s.key;
for (var key in obj ) {
if (!obj[key]) {
// In order to delete: set the path null
dB.ref('transportation/car/' + keys + "/" + key).set(null);
}
}
});
});
To delete data with specific value which false in your case . We needs to fetch all data for a node and then map through the data using keys to delete the data with exact value of object with value false.
let transportationRef = firebase.database().ref().child('transportation/')
transportationRef.child("car").once('value', s => {
if (s.exists()) {
// map through objects returned from transportationRef and map through the objects
Object.keys(s.val()).map(k => {
// deleting the node which contains `false` as value
if(s.val()[k]=="false"){
s.ref.remove()
}
})
}
})
Related
Hi I have a problem in Vue Js. I want to extract some Json Keys to Data Properties to post into backend using axios.
But when I do it seems failed.
Here is my code:
Method() {
post_tamu(){
this.$store.dispatch("POST_TAMU", {
tamu: {
Nama: this.nama_tamu,
NoIdentitas: this.no_identitas,
NoKontak: this.no_handphone,
Instansi: this.instansi,
fotodiri: this.pict_self,
fotoid: this.pict_id
},
karyawan: {
Nama = this.select_karyawan.Nama,
NoKontak = this.select_karyawan.NoKontak,
},
keperluan: this.activity,
SIK: this.sik,
NDA: this.NDA,
CRQ: this.crq,
status: false
}).then(success => {
this.$router.push('/')
}).catch(error => {
this.error = true;
})
},
}
Computed() {
select_karyawan() {
return this.LIST_KARYAWAN.filter(i => {
return this.karyawan === "" || i.Nama == this.karyawan;
// console.log(karyawan)
});
},
}
I think I did wrong in this.select_karyawan.Nama I dont have any idea to extract keys json value from computed properties.
So in below code if i pass ancillaryProductInd as boolean code works, but when I pass it as a string, it does not work. In my understanding the below code should only work when I pass "false" string value and throw error on boolean. Any idea what is the issue here ?
main.ts
request
var rxInfos = [{
"ancillaryProductInd": "false",
"indexID": "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}]
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach((rxInfo) => {
const subQuestion = {
question: []
};
if (rxInfo.ancillaryProductInd !== undefined && rxInfo.ancillaryProductInd === "false") {
subQuestion.question = data;
subQuestionArray.push(subQuestion);
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [{
some data
}]);
Your example code works as expected with a string value "false" and doesnt run the if block when a boolean is used. See my example:
var rxInfos = [
{
ancillaryProductInd: "false",
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
},
{
ancillaryProductInd: false,
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}
];
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach(rxInfo => {
const subQuestion = {
question: []
};
if (
rxInfo.ancillaryProductInd !== undefined &&
rxInfo.ancillaryProductInd === "false"
) {
console.log("no error");
subQuestion.question = data;
subQuestionArray.push(subQuestion);
} else {
console.log("throw error");
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [
{
test: ""
}
]);
I have a onWrite cloud function set up to listen for when a user updates something. I'm trying to delete the oldest child if there are more than 3, this is there I'm at:
exports.removeOld = functions.database.ref('/users/{uid}/media').onWrite(event => {
const uid = event.params.uid
if(event.data.numChildren() > 3) {
//Remove Oldest child...
}
})
Each of these children has a "timestamp" key.
{
"users" : {
"jKAWX7v9dSOsJtatyHHXPQ3MO193" : {
"media" : {
"-Kq2_NvqCXCg_ogVRvA" : {
"date" : 1.501151203274347E9,
"title" : "Something..."
},
"-Kq2_V3t_kws3vlAt6B" : {
"date" : 1.501151232526373E9,
"title" : "Hello World.."
}
"-Kq2_V3t_kws3B6B" : {
"date" : 1.501151232526373E9,
"title" : "Hello World.."
}
}
}
}
}
So in the above example, when the text value is added to "media", the oldest would be delete.
This sample should help you.
You need something like that :
const MAX_LOG_COUNT = 3;
exports.removeOld = functions.database.ref('/users/{uid}/media/{mediaId}').onCreate(event => {
const parentRef = event.data.ref.parent;
return parentRef.once('value').then(snapshot => {
if (snapshot.numChildren() >= MAX_LOG_COUNT) {
let childCount = 0;
const updates = {};
snapshot.forEach(function(child) {
if (++childCount <= snapshot.numChildren() - MAX_LOG_COUNT) {
updates[child.key] = null;
}
});
// Update the parent. This effectively removes the extra children.
return parentRef.update(updates);
}
});
});
You can find all Cloud Functions for Firebase samples here.
I have a JSON that looks like this, I get it from a PHP file that calls Yahoo Finance API,
It's the first time I see a JSON like this.
I looked everywhere but all I manage to do is console log it... I'd like to display it into a table, or a ul, with AJAX
I'd like to access everything and display just what I need or everything.
I tried a bunch of different code snippets from everywhere but couldn't make it work, in three days !...
I'm using scheb/yahoo-finance-api on packagist for that, if it helps.
Thanks for your help.
{
query: {
count: 1,
created: "2017-06-07T12:34:44Z",
lang: "en-US",
results: {
quote: {
symbol: "APLL",
Symbol: "APLL",
LastTradePriceOnly: "0.119",
LastTradeDate: "6/6/2017",
LastTradeTime: "11:13am",
Change: "+0.023",
Open: "0.119",
DaysHigh: "0.119",
DaysLow: "0.110",
Volume: "300"
}
}
}
}
$(function(){
$("#get-data").click(function() {
//do ajax here and load data
var showData = $('#show-data');
var $data = $.getJSON("data.php", function(data) {
// $data = $data.responseText;
function buildTree(data, container) {
$data.forEach(function(node) {
var el = document.createElement(node.tag);
if (Array.isArray(node.content)) {
buildTree(node.content, el);
}
else if (typeof(node.content) == 'object') {
buildTree([node.content], el);
}
else {
el.innerHTML = node.content;
}
container.appendChild(el);
});
}
console.log($data);
buildTree($data, document.body);
});
});
});
That's the one I have for now, I deleted all the others, I took it form here and modified it with no success tho..
Thank you for answering :)
literal notation, not Json.
You can go over this in a for in loop, something like this:
var x = {
query: {
count: 1,
created: "2017-06-07T12:34:44Z",
lang: "en-US",
results: {
quote: {
symbol: "APLL",
Symbol: "APLL",
LastTradePriceOnly: "0.119",
LastTradeDate: "6/6/2017",
LastTradeTime: "11:13am",
Change: "+0.023",
Open: "0.119",
DaysHigh: "0.119",
DaysLow: "0.110",
Volume: "300"
}
}
}
}
for (var key in x) {
if (!x.hasOwnProperty(key)) continue;
var obj = x[key];
for (var prop in obj) {
if(!obj.hasOwnProperty(prop)) continue;
alert(prop + " = " + obj[prop]);
}
}
Is this what you want to achieve?
// let's assume this is your data
var data = {
query: {
count: 1,
created: "2017-06-07T12:34:44Z",
lang: "en-US",
results: {
quote: {
symbol: "APLL",
Symbol: "APLL",
LastTradePriceOnly: "0.119",
LastTradeDate: "6/6/2017",
LastTradeTime: "11:13am",
Change: "+0.023",
Open: "0.119",
DaysHigh: "0.119",
DaysLow: "0.110",
Volume: "300"
}
}
}
};
// prints one li with key and value
function printTree(key, value, container) {
var li = $('<li></li>');
if (typeof value === 'object') {
// value is a nested object, create a new <ul> element for it
li.append(key + ': ');
var ul = $('<ul></ul>');
for (var index in value) {
printTree(index, value[index], ul); // call the function recursively
}
li.append(ul);
} else {
li.text(key + ': ' + value);
}
container.append(li);
}
printTree('data', data, $('#container')); // call the function for the first time
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="container">
This is in literal notation so I assume you've already parsed it into an object. Let's call that object myObject
var myObject={
query : {
count : 1 ,
created : "2017-06-07T12:34:44Z" ,
lang : "en-US" ,
results : {
quote : {
symbol : "APLL" , Symbol : "APLL" , LastTradePriceOnly : "0.119" , LastTradeDate : "6/6/2017" , LastTradeTime : "11:13am" , Change : "+0.023" , Open : "0.119" , DaysHigh : "0.119" , DaysLow : "0.110" , Volume : "300" } } } }
You can access properties as follows:
var myCount = myObject.query.count
console.log(myCount) // logs 1
I'm trying to use ES6 Classes to construct data models (from a MySQL database) in an API that I'm building. I prefer not using an ORM/ODM library, as this will be a very basic, simple API. But, I'm struggling to get my head around how to define these models.
My data entities are (these are just some simplified examples):
CUSTOMER
Data Model
id
name
groupId
status (enum of: active, suspended, closed)
Private Methods
_getState(status) {
var state = (status == 'active' ? 'good' : 'bad');
return state;
}
Requests
I want to be able to do:
findById: Providing a single customer.id, return the data for that specific customer, i.e. SELECT * FROM customers WHERE id = ?
findByGroupId: Providing a group.id, return the data for all the customers (in an array of objects), belonging to that group, i.e. SELECT * FROM customers WHERE groupId = ?
Response Payloads
For each customer object, I want to return JSON like this:
findById(1);:
[{
"id" : 1,
"name" : "John Doe",
"groupId" : 2,
"status" : "active",
"state" : "good"
}]
findByGroupId(2);:
[{
"id" : 1,
"name" : "John Doe",
"groupId" : 2,
"status" : "active",
"state" : "good"
},
{
"id" : 4,
"name" : "Pete Smith",
"groupId" : 2,
"status" : "suspended",
"state" : "bad"
}]
GROUP
Data Model
id
title
Requests
I want to be able to do:
findById: Providing a single group.id, return the data for that specific group, i.e. SELECT * FROM groups WHERE id = ?
Response Payloads
For each group object, I want to return JSON like this:
findById(2);:
{
"id" : 2,
"title" : "This is Group 2",
"customers" : [{
"id" : 1,
"name" : "John Doe",
"groupId" : 2,
"status" : "active",
"state" : "good"
},
{
"id" : 4,
"name" : "Pete Smith",
"groupId" : 2,
"status" : "suspended",
"state" : "bad"
}]
}
Requirements:
Must use ES6 Classes
Each model in its own file (e.g. customer.js) to be exported
Questions:
My main questions are:
Where would I define the data structure, including fields that require data transformation, using the private methods (e.g. _getState())
Should the findById, findByGroupId, etc by defined within the scope of the class? Or, should these by separate methods (in the same file as the class), that would instantiate the object?
How should I deal with the case where one object is a child of the other, e.g. returning the Customer objects that belongs to a Group object as an array of objects in the Group's findById?
Where should the SQL queries that will connect to the DB be defined? In the getById, getByGroupId, etc?
UPDATE!!
This is what I came up with - (would be awesome if someone could review, and comment):
CUSTOMER Model
'use strict';
class Cust {
constructor (custData) {
this.id = custData.id;
this.name = custData.name;
this.groupId = custData.groupId;
this.status = custData.status;
this.state = this._getState(custData.status);
}
_getState(status) {
let state = (status == 'active' ? 'good' : 'bad');
return state;
}
}
exports.findById = ((id) => {
return new Promise ((resolve, reject) => {
let custData = `do the MySQL query here`;
let cust = new Cust (custData);
let Group = require(appDir + process.env.PATH_API + process.env.PATH_MODELS + 'group');
Group.findById(cust.groupId).then(
(group) => {
cust.group = group;
resolve (cust)
},
(err) => {
resolve (cust);
}
);
});
});
GROUP Model
'use strict';
class Group {
constructor (groupData) {
this.id = groupData.id;
this.title = groupData.title;
}
}
exports.findById = ((id) => {
return new Promise ((resolve, reject) => {
let groupData = `do the MySQL query here`;
if (id != 2){
reject('group - no go');
};
let group = new Group (groupData);
resolve (group);
});
});
CUSTOMER Controller (where the Customer model is instantiated)
'use strict';
var Cust = require(appDir + process.env.PATH_API + process.env.PATH_MODELS + 'cust');
class CustController {
constructor () {
}
getCust (req, res) {
Cust.findById(req.params.id).then(
(cust) => {
res(cust);
},
(err) => {
res(err);
}
)
}
}
module.exports = CustController;
This seems to be working well, and I've been able to use Class, Promise and let to make it more ES6 friendly.
So, I'd like to get some input on my approach. Also, am I using the export and required features correctly in this context?
Here is another approach,
Where would I define the data structure, including fields that require data transformation, using the private methods (e.g. _getState())
You should define those fields, relationship in your model class extending the top model. Example:
class Group extends Model {
attributes() {
return {
id: {
type: 'integer',
primary: true
},
title: {
type: 'string'
}
};
}
relationships() {
return {
'Customer': {
type: 'hasMany',
foreignKey: 'groupId'
}
};
}
}
Should the findById, findByGroupId, etc by defined within the scope of the class? Or, should these by separate methods (in the same file as the class), that would instantiate the object?
Instead of having many functions use findByAttribute(attr) in Model Example:
static findByAttribute(attr) {
return new Promise((resolve, reject) => {
var query = this._convertObjectToQueriesArray(attr);
query = query.join(" and ");
let records = `SELECT * from ${this.getResourceName()} where ${query}`;
var result = this.run(records);
// Note: Only support 'equals' and 'and' operator
if (!result) {
reject('Could not found records');
} else {
var data = [];
result.forEach(function(record) {
data.push(new this(record));
});
resolve(data);
}
});
}
/**
* Convert Object of key value to sql filters
*
* #param {Object} Ex: {id:1, name: "John"}
* #return {Array of String} ['id=1', 'name=John']
*/
static _convertObjectToQueriesArray(attrs) {
var queryArray = [];
for (var key in attrs) {
queryArray.push(key + " = " + attrs[key]);
}
return queryArray;
}
/**
* Returns table name or resource name.
*
* #return {String}
*/
static getResourceName() {
if (this.resourceName) return this.resourceName();
if (this.constructor.name == "Model") {
throw new Error("Model is not initialized");
}
return this.constructor.name.toLowerCase();
}
How should I deal with the case where one object is a child of the other, e.g. returning the Customer objects that belongs to a Group object as an array of objects in the Group's findById?
In case of relationships, you should have methods like findRelations, getRelatedRecords.
var customer1 = new Customer({ id: 1, groupId: 3});
customer1.getRelatedRecords('Group');
class Model {
...
getRelatedRecords(reln) {
var targetRelationship = this.relationships()[reln];
if (!targetRelationship) {
throw new Error("No relationship found.");
}
var primaryKey = this._getPrimaryKey();
var relatedObject = eval(reln);
var attr = {};
if (targetRelationship.type == "hasOne") {
console.log(this.values);
attr[relatedObject.prototype._getPrimaryKey()] = this.values[targetRelationship.foreignKey];
} else if (targetRelationship.type == "hasMany") {
attr[targetRelationship.foreignKey] = this.values[this._getPrimaryKey()];
}
relatedObject.findByAttribute(attr).then(function(records) {
// this.values[reln] = records;
});
}
...
}
Where should the SQL queries that will connect to the DB be defined? In the getById, getByGroupId, etc?
This one is tricky, but since you want your solution to be simple put the queries inside your find methods. Ideal scenario will be to have their own QueryBuilder Class.
Check the following full code the solution is not fully functional but you get the idea. I've also added engine variable in the model which you can use to enhance fetching mechanism. All other design ideas are upto your imagination :)
FULL CODE:
var config = {
engine: 'db' // Ex: rest, db
};
class Model {
constructor(values) {
this.values = values;
this.engine = config.engine;
}
toObj() {
var data = {};
for (var key in this.values) {
if (this.values[key] instanceof Model) {
data[key] = this.values[key].toObj();
} else if (this.values[key] instanceof Array) {
data[key] = this.values[key].map(x => x.toObj());
} else {
data[key] = this.values[key];
}
}
return data;
}
static findByAttribute(attr) {
return new Promise((resolve, reject) => {
var query = this._convertObjectToQueriesArray(attr);
query = query.join(" and ");
let records = `SELECT * from ${this.getResourceName()} where ${query}`;
var result = this.run(records);
// Note: Only support 'equals' and 'and' operator
if (!result) {
reject('Could not found records');
} else {
var data = [];
result.forEach(function(record) {
data.push(new this(record));
});
resolve(data);
}
});
}
getRelatedRecords(reln) {
var targetRelationship = this.relationships()[reln];
if (!targetRelationship) {
throw new Error("No relationship found.");
}
var primaryKey = this._getPrimaryKey();
var relatedObject = eval(reln);
var attr = {};
if (targetRelationship.type == "hasOne") {
console.log(this.values);
attr[relatedObject.prototype._getPrimaryKey()] = this.values[targetRelationship.foreignKey];
} else if (targetRelationship.type == "hasMany") {
attr[targetRelationship.foreignKey] = this.values[this._getPrimaryKey()];
}
relatedObject.findByAttribute(attr).then(function(records) {
// this.values[reln] = records;
});
}
/**
* Test function to show what queries are being ran.
*/
static run(query) {
console.log(query);
return [];
}
_getPrimaryKey() {
for (var key in this.attributes()) {
if (this.attributes()[key].primary) {
return key;
}
}
}
/**
* Convert Object of key value to sql filters
*
* #param {Object} Ex: {id:1, name: "John"}
* #return {Array of String} ['id=1', 'name=John']
*/
static _convertObjectToQueriesArray(attrs) {
var queryArray = [];
for (var key in attrs) {
queryArray.push(key + " = " + attrs[key]);
}
return queryArray;
}
/**
* Returns table name or resource name.
*
* #return {String}
*/
static getResourceName() {
if (this.resourceName) return this.resourceName();
if (this.constructor.name == "Model") {
throw new Error("Model is not initialized");
}
return this.constructor.name.toLowerCase();
}
}
class Customer extends Model {
attributes() {
return {
id: {
type: 'integer',
primary: true
},
name: {
type: 'string'
},
groupId: {
type: 'integer'
},
status: {
type: 'string'
},
state: {
type: 'string'
}
};
}
relationships() {
return {
'Group': {
type: 'hasOne',
foreignKey: 'groupId'
}
};
}
}
class Group extends Model {
attributes() {
return {
id: {
type: 'integer',
primary: true
},
title: {
type: 'string'
}
};
}
relationships() {
return {
'Customer': {
type: 'hasMany',
foreignKey: 'groupId'
}
};
}
}
var cust = new Customer({
id: 1,
groupId: 3
});
cust.getRelatedRecords('Group');
var group = new Group({
id: 3,
title: "Awesome Group"
});
group.getRelatedRecords('Customer');
var groupData = new Group({
"id": 2,
"title": "This is Group 2",
"customers": [new Customer({
"id": 1,
"name": "John Doe",
"groupId": 2,
"status": "active",
"state": "good"
}),
new Customer({
"id": 4,
"name": "Pete Smith",
"groupId": 2,
"status": "suspended",
"state": "bad"
})
]
});
console.log(groupData.toObj());