我试图从我的材料搜索对话框中搜索Firebase数据库。我这样做很成功,但是问题是我只能通过标题搜索(我的数据库也包含标题和描述),尽管我尝试了很多对我没有用的东西。
在某个时候,我成功创建了另一个用于搜索描述的搜索功能,但随后它使搜索结果中的标题出现了异常。
我在附上下面的代码,请看一下,让我知道我可以做些什么来搜索标题和描述。
声明和代码(我已从活动代码中跳过了不需要的部分)
materialSearchBar = homeView.findViewById(R.id.searchBar);
materialSearchBar.setHint("Search Ad");
loadSuggest();
materialSearchBar.setLastSuggestions(suggestList);
materialSearchBar.setCardViewElevation(10);
materialSearchBar.addTextChangeListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
List<String> sugest = new ArrayList<String>();
for (String search : suggestList) {
if (search.toLowerCase().contains(materialSearchBar.getText().toLowerCase()))
sugest.add(search);
}
materialSearchBar.setLastSuggestions(sugest);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
materialSearchBar.setOnSearchActionListener(new MaterialSearchBar.OnSearchActionListener() {
@Override
public void onSearchStateChanged(boolean enabled) {
if (!enabled)
mallUsers.setAdapter(firebaseRecyclerAdapter);
}
@Override
public void onSearchConfirmed(CharSequence text) {
startSearch(text);
}
@Override
public void onButtonClicked(int buttonCode) {
}
});
// start search and load suggestions methods
private void startSearch(CharSequence text) {
String searchText = text.toString();
Query query1 = mDatabase1.orderByChild("title").startAt(searchText).endAt(searchText + "\uf8ff");
Query query2 = mDatabase1.orderByChild("description").startAt(searchText).endAt(searchText + "\uf8ff");
FirebaseRecyclerOptions<Ad> firebaseRecyclerOptions2 = new FirebaseRecyclerOptions
.Builder<Ad>()
.setQuery(query1, Ad.class)
.build();
searchAdapter = new FirebaseRecyclerAdapter<Ad, UsersViewHolder1>(firebaseRecyclerOptions2) {
@Override
protected void onBindViewHolder(@NonNull UsersViewHolder1 holder, int position, @NonNull Ad ad1) {
holder.setTitle(ad1.getTitle());
holder.setPrice(ad1.getPrice());
holder.setCategory(ad1.getCategory());
holder.setImage(ad1.getImage(), getContext());
holder.setTime(ad1.getTime());
String user_id = getRef(position).getKey();
final String kk = user_id.toString();
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mew = new Intent(getActivity(), ExpandActivity.class);
mew.putExtra("user_id", kk);
startActivity(mew);
}
});
}
@NonNull
@Override
public UsersViewHolder1 onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view1 = LayoutInflater.from(parent.getContext()).inflate(R.layout
.user_ad_layout, parent,
false);
return new UsersViewHolder1(view1);
}
};
searchAdapter.startListening();
mallUsers.setAdapter(searchAdapter);
}
private void loadSuggest() {
mDatabase1.orderByKey().addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postdataSnapshot : dataSnapshot.getChildren()) {
Ad item = postdataSnapshot.getValue(Ad.class);
if (item != null) {
suggestList.add(item.getTitle());
suggestList.add(item.getDescription());
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
答案 0 :(得分:1)
根据此post,无法将两个查询传递给单个适配器。因此,您可以传递query1
或query2
。
不幸的是,Firebase Realtime数据库不支持对多个属性的查询(有人用SQL术语说“ multiple where子句”),仅支持对单个子属性的查询。因此,您需要创建一个额外的字段来保留两个字段。因此,要实现这一点,您需要创建一个新字段,该字段在数据库中应如下所示:
Firebase-root
|
--- itemId
|
--- title: "valueOfTitle"
|
--- description: "valueOfDescription"
|
--- title_description: "valueOfTitle_valueOfDescription"
因此,如您所见,title_description
属性将要过滤的值组合在一起。但是Firebase实时数据库不支持本机索引编制或在对象中搜索文本字段。此外,下载整个模式以搜索客户端的字段也不切实际。但是,您可以对小型数据集执行此操作,但是正如我之前所说,对于大型数据集不可行。要启用Firebase Real-tme数据库的全文本搜索,建议您使用Algolia之类的第三方搜索服务。
与Firebase Realtime数据库不同,Cloud Firestore允许compound queries。您应该看看这个。因此,在Cloud Firestore中允许以下查询,而无需创建组合属性。
itemIdRef.whereEqualTo("title", "valueOfTitle").whereEqualTo("description", "valueOfDescription");
如果您想在Cloud Firestore中使用Algolia,建议您从此 post 中查看答案。有关更多信息,我还建议您查看此 video 。
答案 1 :(得分:0)
您已经体验了Firebase的最低功能,即查询。但是,例如,如果您在firebase上上传标题和说明,例如,您可以查询多个值:
user:
post:
title: "cake"
description: "yummy"
titledescription: "cake_yummy"
类似的东西。 您可以做的另一件事是
private boolean hasValue = false;
private boolean hasValue1 = false;
onBindViewHolder内的设置值为true,然后一次使用处理程序延迟查询值:
Handler myHandler1 = new Handler();
Runnable myRunnable1 = new Runnable() {
@Override
public void run() {
// query1 here
}
};
Handler myHandler2 = new Handler();
Runnable myRunnable2 = new Runnable() {
@Override
public void run() {
// query2 here
}
};
然后您一次检查一次,直到找到一个值
if(!hasValue){
myHandler1.postDelayed(myRunnable1, 1000);
if(!hasValue1){
myHandler2.postDelayed(myRunnable2, 1500);
} else {
myHandler1.removeCallbacks(myRunnable1);
hasValue1 = false;
} else {
myHandler2.removeCallbacks(myRunnable2);
hasValue2 = false;
}
}
希望有帮助。