我有一个用户集合,我想从数据库中查询所有用户,并将它们显示在RecyclerView
中,除了 mine 。这是我的数据库模式:
users [collection]
- uid [document]
- uid: "fR5bih7SysccRu2Gu9990TeSSyg2"
- username: "John"
- age: 22
- //other users
如何像这样查询数据库:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
Query q = db.collection("users").whereNotEqualTo("uid", uid);
因此,我需要将此查询对象传递给FirestoreRecyclerOptions
对象,以便显示RecyclerView
中的所有其他用户。
这甚至可能吗?如果没有,我该如何解决?谢谢!
编辑:
options = new FirestoreRecyclerOptions.Builder<UserModel>()
.setQuery(query, new SnapshotParser<UserModel>() {
@NonNull
@Override
public UserModel parseSnapshot(@NonNull DocumentSnapshot snapshot) {
UserModel userModel = documentSnapshot.toObject(UserModel.class);
if (!userModel.getUid().equals(uid)) {
return userModel;
} else {
return new UserModel();
}
}
}).build();
答案 0 :(得分:5)
经过数天的努力,终于找到了答案。没有@Raj的帮助,我无法解决这个问题。非常感谢@Raj的耐心和指导。
首先,根据@Frank van Puffelen在此post中的回答提供的答案,我停止寻找可以帮助我将两个查询传递给单个适配器的解决方案。
在这个问题中,我想要实现的只是查询数据库以获取除我之外的所有用户。因此,因为我们不能将两个查询合并到一个实例中,所以我发现可以将两个查询的结果合并。所以我创建了两个查询:
FirebaseFirestore db = FirebaseFirestore.getInstance();
Query firstQuery = db.collection("users").whereLessThan("uid", uid);
Query secondQuery = db.collection("users").whereGreaterThan("uid", uid);
我的用户对象有一个UserModel
(POJO)类。我发现不是一个,而是两种解决问题的方法。第一个是查询数据库以获取与第一个条件相对应的所有用户对象,并将它们添加到列表中。之后,再次查询数据库并获取与第二个条件相对应的其他用户对象,并将它们添加到相同列表中。现在,我有了一个列表,其中包含我需要的所有用户,但一个包含具有查询中特定ID的用户。这是将来访问者的代码:
firstQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
List<UserModel> list = new ArrayList<>();
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
UserModel userModel = document.toObject(UserModel.class);
list.add(userModel);
}
secondQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
UserModel userModel = document.toObject(UserModel.class);
list.add(userModel);
}
//Use the list of users
}
}
});
}
}
});
第二种方法要短得多,因为我这样使用Tasks.whenAllSuccess()
:
Task firstTask = firstQuery.get();
Task secondTask = secondQuery.get();
Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
@Override
public void onSuccess(List<Object> list) {
//This is the list that I wanted
}
});
答案 1 :(得分:4)
Firestore不支持not equal to
操作。因此,您需要在客户端过滤数据。由于您只有一种额外的物品,因此可以将其过滤掉。
为此,您可能需要构建自己的回收器实现,即在将数据添加到回收器适配器数据层时,只要数据符合您的!=
条件,就对它们进行限制。
我还没有研究提供的回收站实现firebase,所以我不能说它是否支持对适配器数据的数据操纵。
这里是开始实施回收者视图的好资源:https://www.androidhive.info/2016/01/android-working-with-recycler-view/
答案 2 :(得分:3)
根据官方的Firestore文档:-
Cloud Firestore不支持以下类型的查询:
带有!=子句的查询。在这种情况下,您应该拆分查询 大于查询和小于查询。例如,尽管 查询子句where(“ age”,“!=”,“ 30”)不支持,您可以 通过组合两个查询获得相同的结果集,其中一个与子句 where(“ age”,“ <”,“ 30”)和带有子句where(“ age”,“>”,30)的子句。
如果您使用的是FirestoreRecyclerAdapter,则FirestoreRecyclerOptions将使用setQuery()方法直接接受查询,因此不允许您执行客户端过滤。
如果您在设置数据时尝试在onBindViewHolder()中应用过滤器,则可能导致回收站视图中的项目为空。为了解决该问题,请参考方法2。
因此,可能的解决方案是在每个文档下的用户集合中创建一个整数字段。例如:-
users [collection]
- uid [document]
- uid: "fR5bih7SysccRu2Gu9990TeSSyg2"
- username: "John"
- age: 22
- check: 100
在此,我创建了一个'check'变量,其值为100。因此,在所有其他文档中将'check'的值设置为小于100。 现在,您可以轻松地进行查询,查找带有check <100的文档:-
Query q = db.collection("users").whereLessThan("check", 100);
这将检索您所有的文档,除了不需要的文档。并且在设置数据时,您可以设置其他参数来跳过检查变量。
方法2(客户端过滤)
我们可以在onBindViewHolder()方法中进行检查,如果检索到的uid与当前用户uid匹配,则将Recycler视图的高度设置为0dp。如:-
ViewUserAdapter.java
public class ViewUserAdapter extends FirestoreRecyclerAdapter<User, ViewUserAdapter.ViewUserHolder>
{
String uid;
FirebaseAuth auth;
public ViewUserAdapter(@NonNull FirestoreRecyclerOptions<User> options)
{
super(options);
auth = FirebaseAuth.getInstance();
uid = auth.getCurrentUser().getUid();
}
@Override
protected void onBindViewHolder(@NonNull ViewUserHolder holder, int position, @NonNull User model)
{
DocumentSnapshot snapshot = getSnapshots().getSnapshot(position);
String id = snapshot.getId();
if(uid.equals(id))
{
RecyclerView.LayoutParams param = (RecyclerView.LayoutParams)holder.itemView.getLayoutParams();
param.height = 0;
param.width = LinearLayout.LayoutParams.MATCH_PARENT;
holder.itemView.setVisibility(View.VISIBLE);
}
else
{
holder.tvName.setText(model.name);
holder.tvEmail.setText(model.email);
holder.tvAge.setText(String.valueOf(model.age));
}
}
}
答案 3 :(得分:1)
开发者好。看起来像 now supported 的 where 操作符是这样使用的:citiesRef.where("capital", "!=", false);
答案 4 :(得分:0)
最简单的解决方案是使用 PagedListAdapter 并为Firestore查询创建自定义的 DataSource 。在数据源中,可以将查询转换为Array或ArrayList,在将数据添加到方法callback.onResult(...)
之前,可以轻松地删除其中的项目。
我在Firestore查询后使用了类似的解决方案来处理数据,以便按时间属性进行过滤和排序,然后在客户端中按质量得分属性进行重新排序,然后再将数据传递回{{1} }。
callback.onResult(...)
答案 5 :(得分:0)
更简单,更早的客户端过滤(将项目添加到列表时):
这样完成后,您可以在客户端使用“不等于”方法,而不会遇到任何Firestore问题。另一个好处是,您不必弄乱适配器,也不必从回收站中不需要的列表项中隐藏视图。
public void getUsers(final ArrayList<Users> usersArrayList, final Adapter adapter) {
CollectionReference usersCollectionRef = db.collection("users");
Query query = usersCollectionRef
.whereEqualTo("is_onboarded", true);
query.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
final String otherUserID = document.getId();
FirebaseUser user = mAuth.getCurrentUser();
String currentUserID = user.getUid();
if (!otherUserID.equals(currentUserId)) {
usersArrayList.add(new User(otherUserID));
adapter.notifyDataSetChanged(); //Ensures users are visible immediately
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
}
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
}
答案 6 :(得分:0)
您不必做所有这一切
只需执行常规查询并通过将getLayoutParams()。height和width分别设置为0即可隐藏布局。参见下面的示例。
if(firebaseUserId.equalIgnoreCase("your_holder_firebase_user_id"){
holder.mainLayout.setVisibility(View.INVISIBLE);
holder.mainLayout.getLayoutParams().height = 0;
holder.mainLayout.getLayoutParams().width = 0;
}else {
//show your list as normal
}
//This will hide any document snapshot u don't need, it will be there but hidden
答案 7 :(得分:0)
这是我的用户名扑朔迷离的解决方案
variable "build_name"