Android Firebase高级模糊搜索,采用levenshtein排序和逐字搜索
搜索是我当前应用程序中最重要的部分之一。它需要感觉像一个快速、准确的全球搜索。该应用程序基于Firebase,我发现Firebase的equalTo()/startAt()组合在这方面相当缺乏 我想要实现的目标:Android Firebase高级模糊搜索,采用levenshtein排序和逐字搜索,android,firebase,firebase-realtime-database,levenshtein-distance,fuzzy-search,Android,Firebase,Firebase Realtime Database,Levenshtein Distance,Fuzzy Search,搜索是我当前应用程序中最重要的部分之一。它需要感觉像一个快速、准确的全球搜索。该应用程序基于Firebase,我发现Firebase的equalTo()/startAt()组合在这方面相当缺乏 我想要实现的目标: 结果按相关性排序 逐字匹配(soöpime应产生上述结果) 搜索多个属性(因此põhjala pime应产生上述结果) 模糊搜索(levenshtein?)-pojala应该匹配Põhjala 我已经做过的 我没有使用equalTo(),而是下载整个分支(例如啤酒),并在其中循环
- 结果按相关性排序
- 逐字匹配(soöpime应产生上述结果)
- 搜索多个属性(因此põhjala pime应产生上述结果)
- 模糊搜索(levenshtein?)-pojala应该匹配Põhjala
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) {
}
});
final ArrayList searchResults=new ArrayList();
FirebaseUtil.getBeersRef().orderByChild(“名称”).addValueEventListener(新的ValueEventListener()){
@凌驾
公共无效onDataChange(最终数据快照ogDS){
int childCounter=0;
对于(DataSnapshot ds:ogDS.getChildren()){
childCounter++;
如果(结果计数器[0]<5){
最终啤酒=ds.getValue(Beer.class);
最后一个字符串beerId=ds.getKey();
//限制为五个结果并删除侦听器
final int finalChildCounter=子计数器;
FirebaseUtil.getBreweriesRef().child(beer.getBreweryId()).addListenerForSingleValueEvent(新值EventListener()){
@凌驾
公共void onDataChange(DataSnapshot DataSnapshot){
Brewery Brewery=dataSnapshot.getValue(Brewery.class);
if(beer.getFullName().toLowerCase().contains(query.toLowerCase())| | brewery.getName().toLowerCase().contains(query.toLowerCase()){
结果计数器[0]=结果计数器[0]+1;
如果(结果计数器[0]<5){
searchResults.add(新的SearchBeerAdapter.BeerBrewery(啤酒,啤酒厂,啤酒厂));
}
}
//在结果结束后初始化适配器
如果(finalChildCounter==ogDS.getChildrenCount()){
SearchBeerAdapter sa=新的SearchBeerAdapter(搜索结果,滑动);
rv.设置适配器(sa);
}
}
@凌驾
已取消的公共void(DatabaseError DatabaseError){
}
});
}
}
}
@凌驾
已取消的公共void(DatabaseError DatabaseError){
}
});
我猜需要做的是,每个匹配都需要在搜索结果中获得一个分数,在我们完成循环之后,ArrayList需要根据这个分数排序。我的主要问题是,考虑到上述标准,如何获得最佳分数。非常欢迎使用任何库或代码示例
提前谢谢。在尝试自己打分和谷歌搜索失败后,我发现了很多。这个相当不错的库使用了levenshtein,但是有一个extractTop()
和extractAll()
功能。它实际上是一个局部模糊搜索,非常适合这种情况
该库只在字符串中搜索,但您可以通过创建仅字符串数组和引用数组来解决这一问题 您不应该直接查询firebase数据库进行搜索,它不是为此而构建的。还有其他工具可以帮助你解决这个问题,你可以查看algolia.com,我之前提到过它是一个潜在的解决方案。嗯,这对我来说不是最好的解决方案。从长远来看,我看到了一家专门的搜索提供商的吸引力,但从短期来看,这意味着将我的数据同步到第二方,可能需要向第二方付费,或者有一个面向用户的徽标,这对他们来说毫无意义。我将保存此链接,但目前我的应用程序对于此链接来说太小了。此外,我并没有在Firebase中搜索。我只是查询然后在结果数组中搜索。