【问题标题】:How do I filter Firestore data?如何过滤 Firestore 数据?
【发布时间】:2019-02-11 21:48:12
【问题描述】:

我的应用允许Users 创建Charts,它们存储在 Firestore 数据库中,如下所示:

charts
    > documentKey1 
         > description = "Example description"
         > name = "Chart name 1"
         > uId = user1Id_string
    > documentKey2
         > description = "Another example description"
         > name = "Chart name 2"
         > uId = user2Id_string
    > documentKey3 
         > description = "Example description again"
         > name = "Chart name 3"
         > uId = user1Id_string

每个用户可以有多个图表。目前,我的MainActivity 从数据库中检索所有当前用户的图表,将它们按给定顺序(由用户设置)进行排序,并在 Fragment 内的 FirebaseRecyclerView 中显示它们。

MainActivity 在 ViewPager 中有 2 个片段。相关的是 FragmentMyCharts,其中包含:

public class FragmentMyCharts extends FragmentChartsList {

    public FragmentMyCharts() {}

    public Query getQuery(FirebaseFirestore databaseReference,
                                String orderBy,
                                Query.Direction direction) {

            // Specify the query which is used to retrieve this user's charts
            return databaseReference.collection("charts")
                    .whereEqualTo("uid", getUid())
                    .orderBy(orderBy, direction);

    }

}

这扩展了FragmentChartsList,如下:

public abstract class FragmentChartsList extends Fragment {

    private FirebaseFirestore mDatabaseRef;
    private ChartListAdapter mAdapter;
    private RecyclerView mRecycler;
    private String mOrder = "name", mFilter;
    private Query.Direction mDirection = Query.Direction.DESCENDING;

    private TextView mLoadingList, mEmptyList;


    public FragmentChartsList() {}

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        // Inflate layout, and find Recycler View which will hold the list
        View rootView = inflater.inflate(
                R.layout.fragment_charts_list, container, false);

        mRecycler = rootView.findViewById(R.id.charts_list);
        mRecycler.setHasFixedSize(true);

        mLoadingList = rootView.findViewById(R.id.loading_list);
        mEmptyList = rootView.findViewById(R.id.empty_list);

        // Set up Layout Manager, and set Recycler View to use it
        LinearLayoutManager mManager = new LinearLayoutManager(getActivity());
        mManager.setReverseLayout(true);
        mManager.setStackFromEnd(true);
        mRecycler.setLayoutManager(mManager);

        // Connect to the database
        mDatabaseRef = FirebaseFirestore.getInstance();

        setOrderAndFilter(mOrder, mDirection, mFilter);

        return rootView;
    }

    public abstract Query getQuery(FirebaseFirestore databaseReference,
                                   String orderBy,
                                   Query.Direction direction);


    public void setOrderAndFilter(String order, Query.Direction direction, String filterString) {

        mOrder = order;
        mDirection = direction;
        mFilter = filterString;

        Query mChartsQuery = getQuery(mDatabaseRef, mOrder, mDirection);

        // Update recycler options
        FirestoreRecyclerOptions<Chart> recyclerOptions = new FirestoreRecyclerOptions.Builder<Chart>()
                .setQuery(mChartsQuery, Chart.class)
                .build();

        mAdapter = new ChartListAdapter(recyclerOptions, getActivity());
        mAdapter.startListening();

        mRecycler.setAdapter(mAdapter);

        mChartsQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {

                if (queryDocumentSnapshots != null) {

                    // Hide "loading lists" text
                    mLoadingList.setVisibility(View.GONE);

                    if(queryDocumentSnapshots.size() > 0) {
                        mEmptyList.setVisibility(View.GONE);
                        mRecycler.setVisibility(View.VISIBLE);
                    }else {
                        // If number of Charts = 0,
                        //    if we have filtered, show "no results"
                        //    otherwise, show "no charts"
                        mEmptyList.setVisibility(View.VISIBLE);
                        mRecycler.setVisibility(View.GONE);
                    }
                }

            }
        });

    }

这引用了ChartListAdapter 类,它的定义如下:

public class ChartListAdapter extends FirestoreRecyclerAdapter<Chart, ChartViewHolder> {

    private Activity mActivity;

    public ChartListAdapter(FirestoreRecyclerOptions<Chart> recyclerOptions, Activity activity) {
        super(recyclerOptions);

        mActivity = activity;

    }

    @Override
    protected void onBindViewHolder(@NonNull ChartViewHolder holder, int position, @NonNull Chart model) {

        final String chartKey = this.getSnapshots().getSnapshot(position).getId();

        model.setKey(chartKey);

        // Set click listener for the chart
        // On click, the user can view the chart
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(mActivity, ActivityViewChart.class);
                intent.putExtra("ChartKey", chartKey);
                mActivity.startActivity(intent);
            }
        });

        // Implement long-click menu
        mActivity.registerForContextMenu(holder.itemView);

        // Bind Chart to ViewHolder
        holder.bindToChart(model);
    }

    @NonNull
    @Override
    public ChartViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_chart, parent, false);

        return new ChartViewHolder(view);
    }

}

因此,目前这会检索所有当前用户的图表,并对它们进行排序和显示。我想要做的是过滤结果,这样用户就可以输入一些搜索文本,并且只显示名称或描述中包含该文本的图表。

我的理解是,我不能在 Firestore 查询中执行此操作,所以我的想法是检索完整的图表列表,然后遍历所有图表,删除任何不符合条件的图表,然后然后显示其余的(列表中不太可能有数百个图表;大多数用户大约有 10 个)。

我不知道该怎么做,我什至不确定这是否是最好的方法。显而易见的地方似乎是当我将snapshotListener 添加到FragmentChartsList 中的ChartsQuery 时,但我找不到从列表中删除单个快照的方法。或者,我可以将所有项目放入recyclerView,然后删除我不想要的项目吗?

谁能指出我正确的方向?我在网上找到的所有内容似乎都是关于删除一个 recyclerView 项目并将其从数据库中删除,我不想这样做。

【问题讨论】:

    标签: android google-cloud-firestore android-recyclerview


    【解决方案1】:

    您可以将以下查询用于搜索过滤功能。

    databaseReference.collection("charts")
                     .whereEqualTo("uid", getUid())
                     .orderBy("name")
                     .startAt(searchText)
                     .endAt(searchtText + "\uf8ff");
    

    将搜索文本传递给 startAt() 和 endAt() 函数,名称就是您的 documentField。

    并将此查询传递给 firestoreAdapter,它将为您提供结果记录。

    【讨论】:

    • 谢谢!我现在就试试!
    • 这似乎不起作用......它的过滤有点随机。通过阅读 startAt 上的文档,看起来这在文档级别上有效,所以它是在图表 id 上过滤,而不是名称/描述?
    • 上述查询仅过滤名称,而不过滤图表 id。它一次只能处理一份提交的文件。您在 orderBy("document filed") 中传递的示例名称或图表 ID 或描述。您需要决定要过滤的字段。如果您想过滤所有内容,则需要使用自定义适配器。它不适用于 Firestore 适配器@Sharon
    猜你喜欢
    • 2020-07-23
    • 1970-01-01
    • 2021-09-18
    • 2021-07-06
    • 2021-11-24
    • 2020-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多