Firebase basics - JavaScript and forms validation - javascript

I want to use Firebase to create coupon codes database. My data structure is following:
[
{
"couponCode": "string",
"isAvailable": true
},
{
"couponCode": "string",
"isAvailable": true
},
...
]
I wont to get couponCode key value and next check value for isAvailable key. If couponCode is valid I want to change value for isAvailable key to false. How to create this validation using Firebase API?

If couponCodes are unique, you're probably better off storing the data like this:
"couponCodes": {
"couponCode1": {
"available": true
},
"couponCode2": {
"available": true
}
}
Now if a user is trying to claim a coupon, you run a transaction on that code:
ref.child('couponCodes').child('couponCode1').transaction(function(current) {
if (current && current.available) {
current.available = false;
// TODO: this is the moment that you'll also want to give the user the discount for the coupon
}
return current;
});

Related

Rest API Patch only 1 field at a time

I'm working on an inline grid editor that calls an express rest api after a single value in the grid is updated. So when a user changes a single field in the grid, I am calling a PATCH request to update the field. However I can't figure out how to only update a single field. When I try it tries to update them all and if there's no value it makes the value NULL in the database. I want to only update a single field, and only the one passed into the API (it could be any of the fields). Here's my method to patch:
// Update record based on TxnID
router.patch('/editablerecords/update', function (req, res) {
let qb_TxnID = req.body.txnid
let type = req.body.type;
let margin = req.body.margin;
if (!qb_TxnID) {
return res.status(400).send({ error:true, message: 'Please provide TxnID' });
}
connection.query("UPDATE pxeQuoteToClose SET ? WHERE qb_TxnID = '" + qb_TxnID + "'", { type, margin }, function (error, results, fields) {
if(error){
res.send(JSON.stringify({"status": 500, "error": error, "response": null }));
//If there is error, we send the error in the error section with 500 status
} else {
res.send(JSON.stringify({ error: false, data: results, message: 'Record updated.' }));
//If there is no error, all is good and response is 200OK.
}
});
});
I will only be updating 1 field at a time, either type or margin, but not both (in this case) at the same time. If I only send one of the fields, the other field becomes null. I've tried to read up on the connection.query() method but can find no information and I don't understand how it builds the query, except that every req.body.value that is passed to it gets used to build the query.
I'm new to building this REST API and feel like I'm missing something simple.
EDIT: I'd like to add, I MAY want to update both fields, but I'd also like to update a single field at a time. Thanks
Per the RFC, the body of a PATCH call should not be the updated representation, but rather a set of instructions to apply to the resource.
The PATCH method requests that a set of changes described in the
request entity be applied to the resource identified by the Request-
URI. The set of changes is represented in a format called a "patch
document" identified by a media type.
One good proposed standard for using PATCH with JSON can be found at https://www.rfc-editor.org/rfc/rfc6902. An example patch document using that standard would be:
[
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]

Optimalization of firebase query. Getting data by ids

I'm new in Firebase. I would like to create an app (using Angular and AngularFire library), which shows current price of some wares. I have list all available wares in Firebase Realtime Database in the following format:
"warehouse": {
"wares": {
"id1": {
"id": "id1",
"name": "name1",
"price": "0.99"
},
"id2": {
"id": "id2",
"name": "name2",
"price": "15.00"
},
... //much more stuff
}
}
I'm using ngrx with my app, so I think that I can load all wares to store as an object not list because normalizing state tree. I wanted load wares to store in this way:
this.db.object('warehouse/wares').valueChanges();
The problem is wares' price will be refresh every 5 minutes. The number og wares is huge (about 3000 items) so one response will be weight about 700kB. I know that I will exceed limit downloaded data in a short time, in this way.
I want limit the loading data to interesing for user, so every user will can choose wares. I will store this choices in following way:
"users": {
"user1": {
"id": "user1",
"wares": {
"id1": {
"order": 1
},
"id27": {
"order": 2
},
"id533": {
"order": 3
}
},
"waresIds": ["id1", "id27", "id533"]
}
}
And my question is:
Is there a way to getting wares based on waresIds' current user? I mean, does it exist way to get only wares, whose ids are in argument array? F.e.
"wares": {
"id1": {
"id": "id1",
"name": "name1",
"price": "0.99"
},
"id27": {
"id": "id27",
"name": "name27",
"price": "0.19"
},
"id533": {
"id": "id533",
"name": "name533",
"price": "1.19"
}
}
for query like:
this.db.object('warehouse/wares').contains(["id1", "id27", "id533"]).valueChanges();
I saw query limits in Angular Fire like equalTo and etc. but every is for list. I'm totally confused. Is there anyone who can help me? Maybe I'm making mistakes in the design of the app structure. If so, I am asking for clarification.
Because you are saving the ids inside user try this way.
wares: Observable<any[]>;
//inside ngOnInit or function
this.wares = this.db.list('users/currentUserId/wares').snapshotChanges().map(changes => {
return changes.map(c => {
const id = c.payload.key; //gets ids under users/wares/ids..
let wares=[];
//now get the wares
this.db.list('warehouse/wares', ref => ref.orderByChild('id').equalTo(id)).valueChanges().subscribe(res=>{
res.forEach(data=>{
wares.push(data);
})
});
return wares;
});
});
There are two things you can do. I don't believe Firebase allows you to query for multiple equals values at once. You can however loop over the array of "ids" and query for each one directly.
I am assuming you already queried for "waresIds" and you've stored those ID's in an array named idArray:
for id in idArray {
database.ref('warehouse/wares').orderByChild('id').equalTo(id).once('value').then((snapshot) => {
console.log(snapshot.val());
})
}
In order to use the above query efficiently you'll have to index your data on id.
Your second option would be to use .childChanged to get only the updated data after your initial fetch. This should cut down drastically on the amount of data you need to download.
Yes , you can get exactly data that you want in firebase,
See official Firebase documents about filtering
You need to get each waresID
var waresID = // logic to get waresID
var userId = // logic to get userId
var ref = firebase.database().ref("wares/" + userId).child(waresID);
ref.once("value")
.then(function(snapshot) {
console.log(snapshot.val());
});
this will return only data related to that waresID or userId
Note: this is javascript code, i hope this will work for you.

How to validate $set 'keys' with MongoDB?

I've got a rather specific case: Using mongoose/mongo and user objects
I want to find and update user in one call.
DB.collection('users').findOneAndUpdate({localId: id} ,{ "$set": { "name": "lla", "usnme": "As"} } ,callback);
Note that 'username' is spelled wrong. Yet mongo updated the first field(name) and does not give any error about the second.
How can I validate the keys I pass in $set without making more than one query?
What MongoDB suggests here is called schema validation:
In your specific case you could run the following command to make sure that no additional ("incorrect") fields can be added by anyone:
db.runCommand({ "collMod": "users", "validator": {
$jsonSchema: {
additionalProperties: false,
properties: {
"_id": {
bsonType: "objectId"
},
"name": {
bsonType: "string"
},
"username": {
bsonType: "string"
}
}
}
}})
Beyond that I cannot really think of any solution since MongoDB is a document database which by default is schemaless and hence won't stop you from creating the fields you tell it to create...

How To Retrieve More Than One "GetValue" From JSON/AJAX search

Ok, I'm struggeling with JSON, AJAX, Javascript and PHP.
Well, actually its only Javascript.
I want to have a input field which operates as a AutoSearch field.
I am using currently EasyAutoComplete.
But that doesnt really matter. What does matter is, that I have to choose one type from the JSON array to be searched. But I want to search both.
Just to make things clear:
- the user should be able to type in "abc" and "123" and find either the number "123456" or "School abc".
- When the user clicks on the result, in both cases the field value should be the number.
Javascript:
$(document).ready(function(){
var options = {
url: function(phrase){
console.log("autocomplete/autocomplete.php?term="+phrase);
return "autocomplete/autocomplete.php?term="+phrase;
},
highlightPhrase: false,
getValue: "instanz_id",
template: {
type: "description",
fields: {
description: "schulname"
}
},
list: {
hideAnimation: {
type: "slide",
time: 400,
callback: function(){}
},
match:{
enabled: true
}
}
};
$("#autocomplete").easyAutocomplete(options);
});
My database structure looks like:
"instanz_id", "schulname"
"123456", "DemoSchule"
Right now, if I type in "123" my JSON return string looks like this:
[{"instanz_id":"123456","schulname":"DemoSchule"}]
And my searchlist: "123456 - DemoSchule". When I click on it, 123456 is the new value of the input field.
How can I get the same item in the searchlist when typing e.g. "Dem" ?
I can change the getValue to "schulname" but then I cannot search using the number...
Can please someone send me in the right direction?

Firebase - how to find all the match items with auto-generated ID, where values are false

Following the techniques on https://www.firebase.com/docs/web/guide/structuring-data.html
Given the url root is: https://myApp.firebaseio.com
And the data is:
// Tracking two-way relationships between users and groups
{
"users": {
"mchen": {
"name": "Mary Chen",
"groups": {
"alpha": true,
"bob": false, // <- I want this
"charlie": true,
"dave": false // <- I want this
}
},
...
},
"groups": {
"alpha": {
"name": "Alpha Group",
"members": {
"mchen": true,
"hmadi": true
}
},
...
}
}
Is it possible to construct a Firebase query to find all the groups that have the value 'false' for user "mchen" (basically I want bob and dave)? How?
e.g. new Firebase('https://myApp.firebaseio.com/users/mchen/groups') ...
In my real code, alpha, bob, charlie and dave are Firebase auto-generated keys, but the same query should solve my problem. (I'm using Firebase Web version)
Thanks in advance.
Finally got it working. I'm not an expert, but I hope this helps anybody not familiar with Firebase:
If you only use Firebase:
var ref = new Firebase('https://myApp.firebaseio.com/users/mchen/groups');
ref.orderByValue().equalTo(false).on('value', function(data){
console.log(data.val());
})
If you use AngularFire:
var ref = new Firebase('https://myApp.firebaseio.com/users/mchen/groups');
$firebaseArray(ref.orderByValue().equalTo(false)).$loaded().then(function(data){
console.log(data);
});
Note:
orderByValue() is the one to use without knowing the keys
Use equalTo(false), not equalTo('false')
$firebaseArray is the one that returns multi items, not $firebaseObject
A rule is also required for performance:
{
"rules": {
"users": {
"$userName": { // A better way would be using an auto-generated ID in here
"groups": {
".indexOn" : ".value" // add index on the value - notice it's .value
}
}
}
}
}

Categories

Resources