Does anyone know if it is possible to programmatically clear all of the data in a Backendless table at once? I found this article that shows how to remove individual objects one at a time but nothing on clearing the whole table at once: https://backendless.com/documentation/data/android/data_deleting_data_objects.htm
I figured out a way to do it but I don't know how efficient it is. Basically, I have a Class called LocalPhoneNum, which make up the objects that will be saved in my app table. The class contains a userID, name and phone num. I query the table to find a user with a specific email (right now there's just one user), then use the foundContacts variable in a loop to delete each object one by one.
String whereClause = "userEmailID = mark";
BackendlessDataQuery dataQuery = new BackendlessDataQuery();
dataQuery.setWhereClause( whereClause );
Backendless.Persistence.of(LocalPhoneNum.class).find(dataQuery, new AsyncCallback<BackendlessCollection<LocalPhoneNum>>(){
#Override
public void handleResponse( BackendlessCollection<LocalPhoneNum> foundContacts )
{
for (LocalPhoneNum temp : foundContacts.getData()){
Backendless.Persistence.of( LocalPhoneNum.class ).remove( temp, new AsyncCallback<Long>()
{
public void handleResponse( Long response )
{
Toast.makeText(getActivity(), "DELETED", Toast.LENGTH_LONG).show();
}
public void handleFault( BackendlessFault fault )
{
Toast.makeText(getActivity(), "NOT DELETED "+fault, Toast.LENGTH_LONG).show();
}
} );
}
Please let me know if there is a better solution or if this one is fine. Thank you!
Use the "bulk delete" operation with the 'where' query like "objectId is not null":
https://backendless.com/documentation/data/rest/data_deleting_data_objects.htm
Related
My recyclerview gets data from json api and populate list of articles. I have now implemented a commenting system with the help of firebase realtime database. I want to show number of comments below each article image in recyclerview. I tried several methods to implement that but all of them are not very effective.
At first I implemented database query based on article unique id for each view but since recyclerview has over 100 articles so it was making over 100 instance calls to database and was causing huge bandwidth problem.
Then I made one query to get all comments count from database and saved them locally in SQLite database and inside recyclerview i query SQLite databse to get comments counts but inserting 100 rows with article id and comments count in SQLite is slow.
What do you guys recommend best method for such task where I will spend least amount of bandwidth and get comment counts also?
My db structure is like this.
get comments method
public void getComments() {
keyrf = FirebaseDatabase.getInstance().getReference().child("Keys");
keyrf.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
HashMap map = new HashMap();
for( DataSnapshot child : dataSnapshot.getChildren() ) {
String childKey = child.getKey();
String c = child.child("c").getValue().toString();
map.put(childKey, c);
addComments(MainActivity.this, childKey, c);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
insert comments method
public static void addComments(Context context, String childKey, String c) {
try {
SQLiteDatabase myDB = context.openOrCreateDatabase("MyDb", Context.MODE_PRIVATE, null);
myDB.execSQL("CREATE TABLE IF NOT EXISTS comments (articleId INTEGER not null unique, comment INTEGER not null)");
String sql = "REPLACE INTO comments (articleId, comment) VALUES (?, ?)";
SQLiteStatement statement = myDB.compileStatement(sql);
statement.bindString(1, childKey);
statement.bindString(2, c);
statement.execute();
} catch (Exception e) {
}
}
What do you guys recommend best method for such task where I will spend least amount of bandwidth and get comment counts also?
The workaround here is to keep a count property somewhere in the database and update that whenever you add/delete child nodes.
So you can consider using a new section that might look similar to this:
Fireabase-root
|
--- numberOfComments
|
--- commentId: 12
|
--- commentId: 10
|
--- commentId: 20
So everytime you add or delete a post, increase / decrease that count by one. And because the number of comments might be updated in an multi user environment, I recommend you to use FirebaseTransactions as explained my answer from this post.
I have a list of notes in room database. I want to choose the list of specific notes depending on some characteristic. For this propose I add a second field note_second_id to a PrimaryKey:
#PrimaryKey(autoGenerate = true)
private long note_id;
private long note_second_id;
Then I create the next query:
#Query("SELECT * FROM " + Constants.TABLE_NAME_NOTE + " WHERE note_second_id = :second_id ")
List<Note> getNotes(long second_id);
When I want to add a new note I use:
long j = activityReference.get().dataBase.getNoteDao().insertNote(note);
deck.setNote_id(j);
deck.setNote_second_id(note000);
where methods .setNote_id(), and setNote_second_id() look like:
public void setNote_id(long deck_id) {this.note_id = note_id; }
public void setNote_second_id(long notesecondid) {
this.note_second_id = notesecondid; }
and note000 is a constant:
Long note000 = 11111L;
And in the activity, where I want these list to be shown I write:
private class RetrieveTaskDeck extends AsyncTask<Void,Void,List<Deck>> {
private WeakReference<MainActivity> activityReference;
// only retain a weak reference to the activity
RetrieveTaskDeck(MainActivity context) {
activityReference = new WeakReference<>(context); }
#Override
protected List<Note> doInBackground(Void... voids) {
if (activityReference.get()!=null)
return activityReference.get().dataBase.getNotesDao().getNotes(note000);
else
return null; }
#Override
protected void onPostExecute(List<Note> notes) {
if (notes !=null && notes.size()>0 ){
activityReference.get().notes.clear();
activityReference.get().notes.addAll(notes);
// hides empty text view
activityReference.get().textViewMsgDeck.setVisibility(View.GONE);
activityReference.get().decksAdapter.notifyDataSetChanged(); } } }
The problem is that this way does not work. It does not show any of the notes. Only when I use the query:
#Query("SELECT * FROM " + Constants.TABLE_NAME_NOTE)
List<Note> getAllNotes();
and
activityReference.get().dataBase.getNotesDao().getAllNotes();
only then I get the list of all notes, which I have. But I need only some specially marked notes to be shown.
What is wrong and what can I do? It seems like something is wrong with query... Maybe someone, who had an experience working with room databes and queries for it, may give some advice...
Actually, I have solved the problem. Here is a solution.
I used the next query:
#Query("SELECT * FROM " + Constants.TABLE_NAME_NOTE + " where note_content LIKE :second_id ")
List<Note> getNotes(String second_id);
Where "note_content" is a name of a column and "second_id" is a first row, written after the column name:
#ColumnInfo(name = "note_content")
private String second_id;
Pay attention, if I write String second_id somewhere after the first String value (second or third) after the proclamation of the column, it does not make search by this word. But in this way, written above, it works.
So, I can set this String value "second_id" of the column dynamically, depending on the task, and a user does not need to know that it even exists. I tried playing with ID in PrimaryKey to solve the same task, but it didn't work. Actually, using of the String value in Column works. Hope it will help someone. Also, if anyone knows how to solve the same task using IDs in PrimaryKey, let me know writing your solution here.
I want to create a nickname to each user who login to my app for the first time. The nickname is the user's firstname and I add a number to it from 1 to 9 000 000. For example kevin Bond could get the nickname kevin123456.
I have all the nicknames stored in a node of my firebase database. Two users shouldn't have the same nickname, so I have to check wether the nickname already exists or not in my database. If it already exists, I want to create another nickname until I get a new nickname.
I currently:
- add a listener to the usernickname node
- in onDataChange I have a for loop to create a nickname, then I check if it already exists with dataSnapshot.hasChild(newNickname). If the nickname doesn't exist I do what I want with the nickname and break the for loop, if it exists I loop the for loop to try another nickname. Here is my code:
mFirebaseDatabase.getReference().child("usernickname").orderByKey().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (int i = 0; i < 9000000; i++) {
final Random random = new Random();
randomNumberId = random.nextInt(9000000);
String newNicknameId = mFirstnameId + String.valueOf(randomNumberId);
//if the nickname already exists we restart the for loop to get a new random number
if (dataSnapshot.hasChild(newNicknameId)) {
i++;
//else if the nickname doesn't exists we create it and stop the loop
} else if (!dataSnapshot.hasChild(newNicknameId)) {
//do what I want...
break;
}
}
}
});
My issue is that I currently have to download all the nicknames node or at least all the nicknames beginning with the user's firstname. It is an issue for me because it could cost me a lot in GB downloaded if I have a lot of users :D
I guess I could use datasnapshot.exists() to check if the nickname exists without having to download all the nicknames, but I don't see how to create another nickname if it already exists. I cannot have a for loop outside of the listener and break it inside of the listener when needed.
Do you see what is the best way to create a new nickname for my users?
Thank you,
Alex
A better approach for unique nicknames would be to append a time stamp to the name:
username + new Date().getTime();
This will add a unique long like 1493808526335 and you can be certain that two users are unlikely to register in the same millisecond with the same name.
You need to use another aproch to check if a user exists. You need to change this line:
dataSnapshot.hasChild(newNicknameId);
with
dataSnapshot.child("userName").getValue().equals(newNicknameId);
In which userName is the name of field in which you store the newNicknameId, assuming your key -> value pair looks like this: userName: "newNicknameId"
Hope it helps.
final Query query = mFirebaseDatabase.getReference().orderByChild("usernickname").equalTo("yourNewNickName");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//here means the value exist
//do whatever you want to do
} else {
//here means the value not exist
//do whatever you want to do
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
use this will solve your problem. :)
I want something like
objectid id name lastname pic
hx5w887 1 name1 lastname1 pic1
lops4wus 2 name2 lastname2 pic2
zh7w8sa 3 name3 lastname3 pic3
I don't want to change the objectId, just I want that field and every time I save an object increment in 1. I am searched a lot in google, about this, it is no possible at least you can something with Cloud Parse code, but I do not know how to make this function, I don't know if "Increment" can help me with this, and I do not know how to run the function anyway.
Parse.Cloud.afterSave("counter", function(request) {
var nameId = request.object.get("name").id;
var Name = Parse.Object.extend("Name");
var query = new Parse.Query(Name);
query.get(nameId).then(function(post) {
post.increment("idkey",+1);
post.save();
}, function(error) {
throw "Got an error " + error.code + " : " + error.message;
});
});
I deploy and
call the function in Android
ParseCloud.callFunctionInBackground("counter", new HashMap<String, Object>(), new FunctionCallback<String>() {
// #Override
public void done(String result, ParseException e) {
if (e == null) {
} else {
// handleError();
}
}
});
But nothing happens, what can be the problem? Sorry my bad english.
You can use ParseCloud 'beforeSave' functionality.
You can declare a code which will run before saving a new object of a specific class.
In this code you query for your class items, order it and get the first item (the highest value) then you can the next value (highest +1) to the new saved object.
For more info you can take a look at Parse documentation and in this thread (it is not in java but it is very similar)
EDIT: Since Parse is not longer is now an open source might be that things have changed.
can please anyone help me with the following:
the following method retrieve data from an online database and i am able to display it but the problem is it takes too long about 1 Minute to display because the application searches through the database to display the latest result from database. can anyone please help me with the application to just go straight to the last rows of the table? so that the application can take few seconds to display data and also be able to refresh every 10 seconds.
here is the method:
private class GetAllProductsTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
myJavaClient = new Client.Builder(appKey, mastersecret,getApplicationContext()).build();
myJavaClient.enableDebugLogging();
myJavaClient.ping(new KinveyPingCallback() {
#Override
public void onSuccess(Boolean arg0) {
System.out.print("Success");
}
#Override
public void onFailure(Throwable arg0) {
System.out.println("Failure");
}
});
try {
myJavaClient.user().loginBlocking(appKey, mastersecret).execute();
System.out.println("Client login -> "+ myJavaClient.user().isUserLoggedIn());
} catch (IOException e) {
System.out.println("Couldn't login -> " + e);
e.printStackTrace();
}
// Ignore for now
myJavaClient.appData("tdSensorData", Sensor.class).get(new KinveyListCallback<Sensor>() {
#Override
public void onSuccess(Sensor[] result) {
Toast.makeText(MainActivity.this,"Get All Worked!\n Got: " + result.length,Toast.LENGTH_LONG).show();
for(Sensor eventID : result)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String currentDateandTime = sdf.format(new Date());
String currentDate = currentDateandTime.substring(0,10);
String times = eventID.getDatetime();
String tim1 = times.substring(0,10);
if (currentDate .compareTo(tim1)==0){
String sens1 = eventID.getSensorr1().toString();
Senso1.setText(sens1);
String sens2 = eventID.getSensorr2().toString();
Senso2.setText(sens2);
String sens3 = eventID.getSensorr3().toString();
Senso3.setText(sens3);
String tmp = eventID.getTemp();
temper.setText(tmp+ " " + "°C");
String dat = eventID.getDatetime();
Device1.setText(dat);
}
}
}
#Override
public void onFailure(Throwable error) {
Toast.makeText(MainActivity.this,
"Get All error: " + error.getMessage(),
Toast.LENGTH_LONG).show();
}
});
return null;
}
}
}
You can put one more boolean column called "fetched data" instead of datatime of creation or update. When it is inserted very first time, you can put the "fetched data" value to false and when it is fetched by the client, you can change it to "true" means it is already fetched. You can fetch the data based on this column value like "fetched data=false" in your query.
You can implement GCM, whenever fresh data will be available to the server it will send it to the client automatically. Hope it will help you.
` Main_Table
Id(primary key) Name Age
1 Balvier 28
2 Kagis 23
User_Table_9920018278
Id(Primary key of Main_Table as Foreign Key)
1
User_Table_9768466084
Id(Primary key of Main_Table as Foreign Key)
1
2 `
GCM is more efficient way to do it, as i said whenever new data will be available to the server, server informs to client automatically. And I tell you steps to fetch data efficiently:
Get the unique id from the client like his phone number and create a table namely that unique number so that every user has separate unique table which has only one column which contains
a. the primary key of main data table as a foreign key
Whenever you insert new data to the main_table, create another entry in the user table also by passing the newly created row's primary key as foreign key.
GCM informs user to download the newly created data to download, or if the data is smaller upto 4kb, you can send the data with gcm notification itself. No need to implement step 2,4,5,6.
On recieve of the notification you check only the user table, is there any row in the user_table.
if yes, then get foreign key of that newly inserted data from user_table and get the whole newly inserted data from the Main_table based on the primary key you get from user table as foreign key.
delete the row from the user_table as you already fetched it.