具有 levenshtein 排序和逐字逐句的 Firebase 高级模糊搜索

Firebase advanced fuzzy search with levenshtein ordering and word by word

搜索是我当前应用程序中最重要的部分之一。它需要给人一种快速、准确、全局搜索的感觉。该应用程序基于 Firebase,我发现 Firebase 的 equalTo() / startAt() 组合在这方面相当缺乏。

我想达到的效果:

我已经做了什么

我没有使用 equalTo(),而是下载了整个分支(例如啤酒),然后循环遍历它,执行我自己的 contains()。这有效并且相当快。但是,它缺少我提到的所有内容。这是当前代码。

           final ArrayList<SearchBeerAdapter.BeerBrewery> searchResults = new ArrayList<>();
            FirebaseUtil.getBeersRef().orderByChild("name").addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(final DataSnapshot ogDS) {
                    int childCounter = 0;
                    for (DataSnapshot ds: ogDS.getChildren()){
                        childCounter++;
                        if (resultCounter[0] < 5) {
                            final Beer beer = ds.getValue(Beer.class);
                            final String beerId = ds.getKey();

                            // Limit to five results and remove listener
                            final int finalChildCounter = childCounter;
                            FirebaseUtil.getBreweriesRef().child(beer.getBreweryId()).addListenerForSingleValueEvent(new ValueEventListener() {
                                @Override
                                public void onDataChange(DataSnapshot dataSnapshot) {
                                    Brewery brewery = dataSnapshot.getValue(Brewery.class);
                                    if (beer.getFullName().toLowerCase().contains(query.toLowerCase()) || brewery.getName().toLowerCase().contains(query.toLowerCase())) {
                                        resultCounter[0] = resultCounter[0] + 1;
                                        if (resultCounter[0] < 5) {
                                            searchResults.add(new SearchBeerAdapter.BeerBrewery(beer, brewery, beerId));
                                        }
                                    }

                                    // Initialize the adapter once we've hit the end of our results
                                    if (finalChildCounter == ogDS.getChildrenCount()){
                                        SearchBeerAdapter sa = new SearchBeerAdapter(searchResults,glide);
                                        rv.setAdapter(sa);
                                    }

                                }

                                @Override
                                public void onCancelled(DatabaseError databaseError) {

                                }
                            });
                        }

                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });

我猜需要做的是每场比赛都需要在 searchResults 中获得一个分数,并且在我们完成循环后,ArrayList 需要根据这个分数进行排序。我的主要问题归结为如何根据上述标准获得最佳分数。任何库或代码示例都将非常受欢迎。

提前致谢。

在尝试自己评分和谷歌搜索失败后,我发现 FuzzyWuzzy。这个相当不错的库使用 levenshtein,但具有 extractTop()extractAll() 功能。它实际上是一个部分模糊搜索,非常适合这种情况。

该库仅在字符串中搜索,但您可以通过创建一个仅包含字符串的数组和一个引用数组来解决这个问题。