this may be simple to you but I am stucked for hours. My Parse User have a relation I setup which is called "Friendsrelation". Now I wanted to load the list of user who are not a friend with the current user so that the currect user can send a request to add him as friend. I cant seems to be able to query users who are not friend (means not in friendsrelation) with currect user. Hope you can help me out here. Much appreciated.
Cheers!
Hi use this query :-
String qry = "select userid FROM users WHERE Not EXISTS (SELECT friendId FROM friendsrelation WHERE friendsrelation.friendId =users.userID and friendsrelation.myid = currentuserID)";
Cursor objCursor = db.rawQuery(qry,null);
ArrrayList<Long> friendsids = new ArrrayList<Long>();
if ((objCursor != null) && (objCursor.getCount() > 0)) {
objCursor.moveToFirst();
while (objCursor.isAfterLast() == false) {
friendsids.add(objCursor.getLong(objCursor.getColumnIndex("userid ")));
}
}
Related
I have a collection where I store user groups. Each group has a group name, group limit and an array of users ID's.
I wonder how the best way to retrieve one group details and then users details, like name, photo, etc.
Right now, I am doing two queries to the database. First retrieving the group data(name, etc), second getting a list of users who has in the user details the information of the group ID:
"syncDesp = a4sQ27xb1wuD2rhONU2K"
I'm afraid of calling the database to many times.
// Get Group details
Preferencias prefs = new Preferencias(view.getContext());
listenGroups = pFirestore.collection("syncDesps").document(prefs.getSyncDesp()).addSnapshotListener((documentSnapshot, e) -> {
if(e != null){
Log.i("dados erro", Objects.requireNonNull(e).getMessage());
}
if(documentSnapshot != null){
String nomeGrupo = Objects.requireNonNull(documentSnapshot.get("nomeGrupo")).toString();
textNomeGrupo.setText(nomeGrupo);
ArrayList membrosGrupo = (ArrayList) Objects.requireNonNull(documentSnapshot.get("syncDesp"));
}
});
// Get User Details
FirebaseFirestore grupoFire = FirebaseFirestore.getInstance();
grupoFire.collection("usuarios")
.whereEqualTo("syncDesp", prefs.getSyncDesp())
.addSnapshotListener((queryDocumentSnapshots, e1) -> {
listaUsuarios.clear();
if(e != null){
Log.i("dados erro", Objects.requireNonNull(e1).getMessage());
}
for(DocumentSnapshot usuarioSnapshot : Objects.requireNonNull(queryDocumentSnapshots).getDocuments()){
String idU = (usuarioSnapshot.get("id") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("id")).toString();
String nomeUsuario = (usuarioSnapshot.get("nome") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("nome")).toString();
String fotoUsuario = (usuarioSnapshot.get("imgUsuario") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("imgUsuario")).toString();
UsuarioMeuGrupo usuarioMeuGrupo = new UsuarioMeuGrupo();//
usuarioMeuGrupo.setIdUsuario(idU);
usuarioMeuGrupo.setNome(nomeUsuario);
usuarioMeuGrupo.setFoto(fotoUsuario);
listaUsuarios.add(usuarioMeuGrupo);
}
adaptera.setOnItemClickRemoverListener(uMeuGrupo -> {
Log.i("dados uMeuGrupo Clic", uMeuGrupo.getNome());
});
adaptera.notifyDataSetChanged();
});
I wonder if I should query the group collection separately from the users collection or if there is a way of making only one function to retrieve data from both collections.
It's not possible to make a single query in Cloud Firestore span multiple collections. There is no join-like operation like you have in SQL. The only exception to this is collection group queries, which doesn't apply to your situation.
What you're doing right now is probably the best you can do with the database structure you have. If you want fewer queries, you'll have to do something to restructure your data to support that.
I'm using this query to fetch the posts by user A and sort by timestamp.
This below query fetches the posts by user A but it doesn't sort by date.
mDatabase = FirebaseDatabase.getInstance().getReference("posts");
String UID = "userA";
Query myTopPostsQuery = mDatabase.equalTo(UID).orderByChild("UID");
I tried using below query, but it returns an empty set.
Query myTopPostsQuery = mDatabase.equalTo(UID).orderByChild("date");
What is the right way to achieve my result?
This is my Data Structure:
posts
-KlgYXK01ezPjk
UID: "YiXgM3qgqcsd"
date: 1496428200000
post: "This is a Test Post by user A"
,
-KlgYXK01ezPpl
UID: "YiXgM3qgqcsd"
date: 1496428220022
post: "This is another Test Post by user A"
,
-KlgYXK01ezKjk
UID: "YiXCWsdj712"
date: 1496428203000
post: "This is a Test Post by user B"
,
Well this may not be the exact answer you are expecting but it helps when your app scales up.
I recommend you use a fan out data structure.
By this create a separate node user-posts where you store all the posts by individual users like below:
user-posts
-YiXgM3qgqcsd //this us A's UID
KlgYXK01ezPjket4ery62
post: "This is a Test Post by user A"
date: 1496428200000
author:'A'
KlgYXK01ezPjket4ery62
post: "This is a 2nd Test Post by user A"
date: 1496428500000
author:'A'
KlgYXK01ezPjket4ery62
post: "This is a 3rd Test Post by user A"
date: 1496428600000
author:'A'
-YiXCWsdj712 //this us B's UID
KlgYXK01ezPjket4ery62
post: "This is a Test Post by user B"
date: 1496428200000
author:'B'
Now you can query for A's posts lik this:
mDatabase = FirebaseDatabase.getInstance().getReference("user-posts");
String UID = "userA";
Query myTopPostsQuery = mDatabase.child(UID).limitToLast(10);
Since pushing data into a node creates a unique key which are by default in chronological order you don't have to worry about sorting by timeline as you are using limitToLast() which gives you posts from the bottom i.e latest
So its better you push data to different nodes posts and user-posts whenever a user creates a post. This is better as writing data is cheap in firebase as compared to reading data
Now you can just pull out data from ref "user-posts/UID" instead of firebase querying data fromposts filtering all the posts by user A then again ordering by timeline which will be expensive and slow if you have many number of posts
When it comes to pushing data to different nodes i.e posts and user-posts this could be cheap and you can use updateChildren() method like below:
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
// Generate a new push ID for the new post
Firebase newPostRef = ref.child("posts").push();
String newPostKey = newPostRef.getKey();
// Create the data we want to update
Map newPost = new HashMap();
newPost.put("title", "New Post");
newPost.put("content", "Here is my new post!");
Map updatedUserData = new HashMap();
updatedUserData.put("user-posts/" + newPostKey, true);
updatedUserData.put("posts/" + newPostKey, newPost);
// Do a deep-path update
ref.updateChildren(updatedUserData, new Firebase.CompletionListener() {
#Override
public void onComplete(FirebaseError firebaseError, Firebase firebase) {
if (firebaseError != null) {
System.out.println("Error updating data: " + firebaseError.getMessage());
}
}
});
You could refer to the firebase blog post here
I am new to firebase and Nosql databases. I have gone through the documentations already, but I cannot seem to get my head around a concept.
I have gone through almost every question on here about it, but everyone just seem to conveniently skip the little detail i am looking for.
Suppose I have successfully registered my users using firebaseauth, and can log them in and out, I have my database rules as follows
{
"rules": {
"users":{
"$userid":{
".read": "auth !== null && auth.uid == $userid",
".write": "auth !== null && auth.uid == $userid"
}
}
}
}
Great!, now thats the basic database for a multiuser application. My question is that the users data doesnt get pushed to database from auth automatically, so i have to do a
mRef = FirebaseDatabase.getInstance().getReference();
mUserRef = mRef.child("users");
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String uid = mAuth.getCurrentUser().getUid();
String name = "User " + uid.substring(0, 6);
Userid userid = new Userid(uid);
mUserRef.push().setValue(userid, newDatabaseReference.CompletionListener() {
and so on, on the registeractivity so any userid can have its own node under users where i can post any user specific data.
I have not implemented this yet, but i forsee that for any read or write data performed by a user will have to search every node to find its own userid, which would take a lot of time when you scale up to like a lot of users and im sure firebase is better than that. So is this how firebase expect us to handle user stuff or does every user just have his own database instance
The push() method creates a new, random ID. This is useful for things like messages in a chat application, but is likely not what you are looking for.
I think you mean to do this:
// Get current UID
String uid = mAuth.getCurrentUser().getUid();
// Get reference to /users/<uid>
DatabaseReference ref = mUserRef.child(uid);
// Set the value of /users/<uid> to the UserId
Userid userid = new Userid(uid);
ref.setValue(userid);
Am not a learner to boolean expressions but this seems to be giving me a bit of an headache.
In my app when i search for a user,I am recieving certain values from my datase using this MYSQL statement.
SELECT `u3`.`username`,
CASE WHEN `u3`.`username` IS NULL THEN 'Not Existing'
ELSE 'Existing' END is_following
FROM `userinfo` `u3` WHERE `u3`.`username` LIKE '%".mysql_real_escape_string($data)."%' OR `u3`.`email` LIKE '%".mysql_real_escape_string($data)."%'
UNION
SELECT `u2`.`username`,
CASE WHEN `u2`.`username` IS NULL THEN 'Follow'
ELSE 'Following' END is_following
FROM
`userinfo` `u1` LEFT JOIN `followers` `f`
ON `u1`.`username` = `f`.`source_id`
LEFT JOIN `userinfo` `u2`
ON `f`.`destination_id` = `u2`.`username`
AND (`u2`.`username` LIKE '%".mysql_real_escape_string($data)."%' OR `u2`.`email` LIKE '%".mysql_real_escape_string($data)."%')
WHERE
`u1`.`username` = '$name'
Now the syntax above would return these set of values, a username and My own metadata. For example it would return
set of values 1: (davies and Existing)[if davies is in the userinfo table] AND (davies and Following)[if davies is following halex in the followers table]
OR
set of values 2: (null and Not Existing)[if davies is not in the userinfo table] AND (null and not followed)[davies does not exist]
OR
set of values 3: (davies and Existing)[if davies is in the userinfo table] AND (null and Not Following)[if davies is not following halex]
These are the set of values i recieve and i need an if statement to sieve through so i can display to my users this simple information
davies and Following OR davies and Follow[if davies is not following halex] OR User Does not Exist
Now am not sure if i should change the structure of my SOL statement or i could get a better way of handling this logic with if and else statements
This was the structure of my if else statement but it doesn't seem to work the way i want it to
if(username != null && metadata.contains("Existing"))//user exist
{
value = username;
//user exists but skip
}else
{
if(username != null)
{
map = new HashMap<String, String>();
map.put(TAG_USERNAME, value);
map.put(TAG_METADATA, metadata);
listvalue.add(map);
}else
{
//user does not exist
Log.i("search ", "user does not exist");
}
}
The codes above belongs to android.
Thanks any suggestion is appreciated. Thanks again in Advance.
What if you split your query into two parts? Querying for one set of information at a time will make things simpler and easier to debug.
I could imagine doing something that looks like this (in pseudo-code):
query = "SELECT username
FROM `userinfo` `u3`
WHERE `u3`.`username` LIKE '%".mysql_real_escape_string($data)."%'
OR `u3`.`email` LIKE '%".mysql_real_escape_string($data)."%'"
var result = db.execute(query);
// set to true if the above query returns at least one row
bool user_exists = (result.RowCount() > 0)
var username = (user_exists)? result.GetRow().GetField("username") : null;
if(user_exists)//user exist
{
value = username;
//user exists but skip
} // ....
(I've only replicated the functionality pertaining to your UNION's first SELECT statement; the logic associated with the second statement can be similarly rewritten.)
in my app i have two edit boxes for email and username. Whatever the user types in it i am trying to move it over an url as follows
http//xxxxxxx.com/id?mail=*email&user=*usernane
By this i am getting a return data from the url, this is what i am doing if network is available. But if network is not available i am storing those two values in Sqlite database and in another activity if network is available i will be fetching the above said data and i will move them to the server.
My problem is, at the time of network not available if the user tries to send two set of username and email to the server it gets stored in database. How can i store those values in an array and how can i fetch them one by one. Please help me friends
Following is the part of my code for database
off = openOrCreateDatabase("Offline.db", SQLiteDatabase.CREATE_IF_NECESSARY, null);
off.setVersion(1);
off.setLocale(Locale.getDefault());
off.setLockingEnabled(true);
final String CREATE_TABLE_OFFLINEDATA ="CREATE TABLE IF NOT EXISTS offlinedata(spotid INTEGER, username TEXT, email TEXT);";
off.execSQL(CREATE_TABLE_OFFLINEDATA);
ContentValues values = new ContentValues();
values.put("id", millis);
values.put("name", username);
values.put("mail", email);
off.insert("offlinedata", null, values);
Cursor con = off.rawQuery("select * from offlinedata" , null);
if (con != null )
{
if (con.moveToFirst())
{
do
{
int spotid = con.getInt(con.getColumnIndex("id"));
String first = con.getString(con.getColumnIndex("username"));
String middle = con.getString(con.getColumnIndex("email"));
}
while (con.moveToNext());
}
}
off.close();
Please help me friends....
From looking at your sample code, it seems like you're storing them properly(ish), and you've managed an exhaustive job fetching them in a really narrow scope, so make first and middle more globalish and since you have two strings available, put them in an array.
Though I must say if this is your actual code it probably won't work the way you want this whole offline thing to work.