如何从Firestore查询中排除元素?

Ioa*_* P. 6 java android kotlin firebase google-cloud-firestore

我有用户的集合,我想从数据库中查询所有用户,并在显示它们RecyclerView除一人外,.这是我的数据库架构:

users [collection]
  - uid [document]
     - uid: "fR5bih7SysccRu2Gu9990TeSSyg2"
     - username: "John"
     - age: 22
  - //other users
Run Code Online (Sandbox Code Playgroud)

如何查询数据库如下:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
Query q = db.collection("users").whereNotEqualTo("uid", uid);
Run Code Online (Sandbox Code Playgroud)

所以我需要将这个查询对象传递给一个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();
Run Code Online (Sandbox Code Playgroud)

Ioa*_* P. 6

经过几天和几天的努力,我终于找到了答案.没有@Raj的帮助,我无法解决这个问题.非常感谢@Raj的耐心和指导.

首先,根据@Frank van Puffelen在这篇文章的回答中提供的答案,我停止寻找可以帮助我将两个查询传递给单个适配器的解决方案.

在这个问题中,我想要实现的只是查询数据库以获得除了一个以外的所有用户,我.因为我们不能将两个查询组合到一个实例中,我发现我们可以组合两个查询的结果.所以我创建了两个查询:

FirebaseFirestore db = FirebaseFirestore.getInstance();
Query firstQuery = db.collection("users").whereLessThan("uid", uid);
Query secondQuery = db.collection("users").whereGreaterThan("uid", uid);
Run Code Online (Sandbox Code Playgroud)

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
                    }
                }
            });
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

第二种方法会短得多,因为我这样使用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
        }
});
Run Code Online (Sandbox Code Playgroud)


Raj*_*Raj 5

根据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
Run Code Online (Sandbox Code Playgroud)

在此,我创建了一个值为 100 的 'check' 变量。因此,将所有其他文档中的 'check' 值设置为小于 100。现在,您可以轻松地进行查询以查找带有 check<100 的文档:-

Query q = db.collection("users").whereLessThan("check", 100);
Run Code Online (Sandbox Code Playgroud)

这将检索除您不想要的文档之外的所有文档。在设置数据时,您可以设置其他参数,跳过检查变量。

方法二(客户端过滤)

我们可以在 onBindViewHolder() 方法中应用检查,如果检索到的 uid 与当前用户 uid 匹配,则将 Recycler 视图的高度设置为 0dp。作为:-

视图用户适配器.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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*nes 5

2021 更新:支持

你好,开发者。看起来现在使用 where 运算符支持这一点,如下所示:citiesRef.where("capital", "!=", false);