I have ran the android version of bluelist tutorial in bluemix.
This app saves data as key-value. For example firstname:.
What if i want to store last name too? Can i create a second "column" or should i make my "person" object a json string and store it?
Check out the tutorial here (http://mbaas-gettingstarted.ng.bluemix.net/android). You can store a Java object in the mobile data service. Behind the scenes it is storing JSON for you. If you want you can obviously store straight JSON but it was abstracted a bit so it models more closley how Java dev's use OO to store and access data.
Scroll down to the data operations bit (http://mbaas-gettingstarted.ng.bluemix.net/android#data-operations), you can store and access data normally as you would through a class in Java.
What i have done eventually is that i stored a json string like
{"firstname":"John","lastname":"Foo"}
In the bluelist application i maintain 2 Lists, one for the whole object and one for the fistsnames only.
By this way i see only the firstname but i can store more than one properties.
(of course as there is one editbox i can set and edit only one property. The second property is a static string - eg it is always John - but i just wanted to test the functionality of the key-value database so it is ok for me.)
This is the accepted answer so far. If there is any other way please answer with an example as i am not too much familiar with this kind of database.
if its a web application,you can use similar logic like below:
var newUser = {
'username': $('#addUser fieldset input#inputUserName').val(),
'email': $('#addUser fieldset input#inputUserEmail').val(),
'fullname': $('#addUser fieldset input#inputUserFullname').val(),
'age': $('#addUser fieldset input#inputUserAge').val(),
'location': $('#addUser fieldset input#inputUserLocation').val(),
'gender': $('#addUser fieldset input#inputUserGender').val()
}
// Use AJAX to post the object to our adduser service
$.ajax({
type: 'POST',
data: newUser,
url: '/users/adduser',
dataType: 'JSON'
}).done(function( response )
You can follow below link for more details on how to add new column and doing insert/update/delete operation on this:
http://cwbuecheler.com/web/tutorials/2014/restful-web-app-node-express-mongodb/
Related
I'm a newbie in Android. I'm making a crypto currency tracker. I'm using a Korean exchange API. But, when I read JSON data as String, it's a little different from what I found in literature.
In the red bracket, there are some data but are classified as the String like "BTC, ETH". And I learned in a book like this
String timestamp;
String payment_currency; // payment currency(USD, KRW...)
ArrayList<BidAskBithumb> bids = new ArrayList<BidAskBithumb>(); // Bids
ArrayList<BidAskBithumb> asks = new ArrayList<BidAskBithumb>(); // Asks
Every property is saved in String and Arrays. But in that JSON data, there is currency's name like BTC or ETH after payment_currency String. I don't know I have to make every class file like BTC.java or ETH.java. How can I solve this?
This is the JSON response I'm getting.
I read all the currency's data:
The original API documentation link.
I don't know I have to make every class file like BTC.java or ETH.java. How can I solve this?
No, you dont have to create new class files for them, you need to create model class according to your json file. & handle its behaviour.
You can try this to create your model.
I've read the Firebase docs on Stucturing Data. Data storage is cheap, but the user's time is not. We should optimize for get operations, and write in multiple places.
So then I might store a list node and a list-index node, with some duplicated data between the two, at very least the list name.
I'm using ES6 and promises in my javascript app to handle the async flow, mainly of fetching a ref key from firebase after the first data push.
let addIndexPromise = new Promise( (resolve, reject) => {
let newRef = ref.child('list-index').push(newItem);
resolve( newRef.key()); // ignore reject() for brevity
});
addIndexPromise.then( key => {
ref.child('list').child(key).set(newItem);
});
How do I make sure the data stays in sync in all places, knowing my app runs only on the client?
For sanity check, I set a setTimeout in my promise and shut my browser before it resolved, and indeed my database was no longer consistent, with an extra index saved without a corresponding list.
Any advice?
Great question. I know of three approaches to this, which I'll list below.
I'll take a slightly different example for this, mostly because it allows me to use more concrete terms in the explanation.
Say we have a chat application, where we store two entities: messages and users. In the screen where we show the messages, we also show the name of the user. So to minimize the number of reads, we store the name of the user with each chat message too.
users
so:209103
name: "Frank van Puffelen"
location: "San Francisco, CA"
questionCount: 12
so:3648524
name: "legolandbridge"
location: "London, Prague, Barcelona"
questionCount: 4
messages
-Jabhsay3487
message: "How to write denormalized data in Firebase"
user: so:3648524
username: "legolandbridge"
-Jabhsay3591
message: "Great question."
user: so:209103
username: "Frank van Puffelen"
-Jabhsay3595
message: "I know of three approaches, which I'll list below."
user: so:209103
username: "Frank van Puffelen"
So we store the primary copy of the user's profile in the users node. In the message we store the uid (so:209103 and so:3648524) so that we can look up the user. But we also store the user's name in the messages, so that we don't have to look this up for each user when we want to display a list of messages.
So now what happens when I go to the Profile page on the chat service and change my name from "Frank van Puffelen" to just "puf".
Transactional update
Performing a transactional update is the one that probably pops to mind of most developers initially. We always want the username in messages to match the name in the corresponding profile.
Using multipath writes (added on 20150925)
Since Firebase 2.3 (for JavaScript) and 2.4 (for Android and iOS), you can achieve atomic updates quite easily by using a single multi-path update:
function renameUser(ref, uid, name) {
var updates = {}; // all paths to be updated and their new values
updates['users/'+uid+'/name'] = name;
var query = ref.child('messages').orderByChild('user').equalTo(uid);
query.once('value', function(snapshot) {
snapshot.forEach(function(messageSnapshot) {
updates['messages/'+messageSnapshot.key()+'/username'] = name;
})
ref.update(updates);
});
}
This will send a single update command to Firebase that updates the user's name in their profile and in each message.
Previous atomic approach
So when the user change's the name in their profile:
var ref = new Firebase('https://mychat.firebaseio.com/');
var uid = "so:209103";
var nameInProfileRef = ref.child('users').child(uid).child('name');
nameInProfileRef.transaction(function(currentName) {
return "puf";
}, function(error, committed, snapshot) {
if (error) {
console.log('Transaction failed abnormally!', error);
} else if (!committed) {
console.log('Transaction aborted by our code.');
} else {
console.log('Name updated in profile, now update it in the messages');
var query = ref.child('messages').orderByChild('user').equalTo(uid);
query.on('child_added', function(messageSnapshot) {
messageSnapshot.ref().update({ username: "puf" });
});
}
console.log("Wilma's data: ", snapshot.val());
}, false /* don't apply the change locally */);
Pretty involved and the astute reader will notice that I cheat in the handling of the messages. First cheat is that I never call off for the listener, but I also don't use a transaction.
If we want to securely do this type of operation from the client, we'd need:
security rules that ensure the names in both places match. But the rules need to allow enough flexibility for them to temporarily be different while we're changing the name. So this turns into a pretty painful two-phase commit scheme.
change all username fields for messages by so:209103 to null (some magic value)
change the name of user so:209103 to 'puf'
change the username in every message by so:209103 that is null to puf.
that query requires an and of two conditions, which Firebase queries don't support. So we'll end up with an extra property uid_plus_name (with value so:209103_puf) that we can query on.
client-side code that handles all these transitions transactionally.
This type of approach makes my head hurt. And usually that means that I'm doing something wrong. But even if it's the right approach, with a head that hurts I'm way more likely to make coding mistakes. So I prefer to look for a simpler solution.
Eventual consistency
Update (20150925): Firebase released a feature to allow atomic writes to multiple paths. This works similar to approach below, but with a single command. See the updated section above to read how this works.
The second approach depends on splitting the user action ("I want to change my name to 'puf'") from the implications of that action ("We need to update the name in profile so:209103 and in every message that has user = so:209103).
I'd handle the rename in a script that we run on a server. The main method would be something like this:
function renameUser(ref, uid, name) {
ref.child('users').child(uid).update({ name: name });
var query = ref.child('messages').orderByChild('user').equalTo(uid);
query.once('value', function(snapshot) {
snapshot.forEach(function(messageSnapshot) {
messageSnapshot.update({ username: name });
})
});
}
Once again I take a few shortcuts here, such as using once('value' (which is in general a bad idea for optimal performance with Firebase). But overall the approach is simpler, at the cost of not having all data completely updated at the same time. But eventually the messages will all be updated to match the new value.
Not caring
The third approach is the simplest of all: in many cases you don't really have to update the duplicated data at all. In the example we've used here, you could say that each message recorded the name as I used it at that time. I didn't change my name until just now, so it makes sense that older messages show the name I used at that time. This applies in many cases where the secondary data is transactional in nature. It doesn't apply everywhere of course, but where it applies "not caring" is the simplest approach of all.
Summary
While the above are just broad descriptions of how you could solve this problem and they are definitely not complete, I find that each time I need to fan out duplicate data it comes back to one of these basic approaches.
To add to Franks great reply, I implemented the eventual consistency approach with a set of Firebase Cloud Functions. The functions get triggered whenever a primary value (eg. users name) gets changed, and then propagate the changes to the denormalized fields.
It is not as fast as a transaction, but for many cases it does not need to be.
We are getting the request from Android app as json array. For example:
$var = [{"username":"kp","mailid":"kp#gmail.com","phoneno":"9876543563","groupname":"android"}]';
I want to make this static data (kp, kp#gmail.com, 9876543563, android) as dynamic to insert the values into database.
In what method we are getting the data? And from an android app, is it POST or GET variable, or an other method? Please let me know how to make this value dynamic which is coming from the android app.
How to do you want to send the data from Android App? Is it needed to be namely JSON-format?
I think the most useful case is to use usual, e.g., POST data and retrieve this using base methods to save it inside PHP. You can use, of course, GET format for 'short' request.
For instance,
Android sends using GET: http://yourcompany.com/senddata?username=name&mailid=e#yourmail.com
You PHP code (very-very-very simple approach):
/// ... initialization...
$sql = "INSERT INTO users (username, email) VALUES ('". ($_POST["username"]) . "', '". ($_POST["mailid"]) . "')";
mysqli_query($conn, $sql)
PHP insert example
To create POST or GET request in Android I would recommend to use JSOUP library
Download
A simple example for jsoup:
Document doc = Jsoup.connect("http://yourcompany.com/url?var1=a").get();
I have to submit data from 30 pages into the server.These datas from 30 pages are to be made into a single string and that i have to upload that single string into the server using json.
Each page may contain many answers tht may be either in plain text(value we receive from edit text),from check boxes(yes or no) and so on.....please suggest me a way to add all these data into a single string and upload it using json.
Based on the comment I suspect that you believe that you need to treat these "pages" as strings that you concat. However, what I think you're overlooking is that JSON is pretty versatile in how you add objects to it.
So, let's say you have the thing that you want to ship to your server and you call it
JSONObject myEntireFile = new JSONObject();
you can now add stuff to it at any time like this...
JSONObject page1 = new JSONObject();
myEntireFile.put("page1", page1);
meanwhile you can put whatever you want IN page 1 (cause that's just another serialized container).
You can keep doing this until you're ready to send it, at which time you just call
myEntireFile.toString();
which will convert your object into one long, well formatted, JSON string, that you can then open store for later use.
Suppose I have a json string like this:
{ ... "key1":"value1"; ... }
with a key1-value1 pair somewhere deep down the json structure (which includes other things such as array, dictionary, etc...). I don't know exactly (and don't care) how the exact structure of the json is.
Is there a simple way to extract the "value1" ? (if there are 2 "key1" in the json string then I just need the first one).
As far as I know, you have no chance of doing it manually.
If you really don't know what's the structure of the JSON string you're expecting, you can try a graph search approach, such as DFS (http://en.wikipedia.org/wiki/Depth-first_search).
For every key, check if it is an array.
If so, go inside and repeat the procedure. If nothing was found in a given array, backtrack.
Interrupt your process once you have found your key.