2016-09-27 150 views
5

我是Firebase和NoSQL的新手。我有一个Android演示,其中有一个城市自动填充文本字段,我想在输入时填充Firebase数据库中的城市。从Android中的Firebase实时数据库检索数据

{ "cities":{ 
     "Guayaquil":true, 
     "Gualaceo":true, 
     "Quito":true, 
     "Quevedo":true, 
     "Cuenca":true, 
     "Loja":true, 
     "Ibarra":true, 
     "Manta":true 
    } 
} 

这是我到目前为止。

如何从数据库中以字母(键盘输入)开头的城市检索?如果我开始输入“G”,我想收到“瓜亚基尔”和“Gualaceo”。

如果我使用orderByValue总是返回一个空的快照。

如果我用orderByKey返回整个列表。

Query citiesQuery = databaseRef.child("cities").startAt(input).orderByValue(); 
    citiesQuery.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      List<String> cities = new ArrayList<String>(); 
      for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { 
       cities.add(postSnapshot.getValue().toString()); 
      } 

注:如果你能推荐一个更好的数据结构,欢迎您。

+0

多大将城市这个数据库是什么?您的应用程序是否可以将数据库中的数据读入本地副本(如某种数组),然后使用本地逻辑在打字时仅显示适当的值? – Ryan

+0

最初它将在10左右,但可以增加到100.我希望这个功能是“在线”的,所以我可以添加新的城市,而不需要在本地存储 –

+0

哦,这很好。就处理器和网络而言,100个小字符串实际上什么都不是,所以它肯定会很快。让我通过本地存储来澄清我的意思。我的意思是在运行时在内存中,这就是全部。我不是说要在设备存储器或类似的东西中存储一个副本。我的意思是,将城市读入数组,然后使用该数组显示数据。当数据库发生变化时,您可以非常轻松地立即更新阵列,但我怀疑它会经常更改。查看我的答案,以获得更多关于我在想什么的解释。 – Ryan

回答

6

@NicholasChen发现了这个问题。但这是你用3来实现的方式。X SDK:

DatabaseReference cities = databaseRef.child("cities") 
Query citiesQuery = cities.orderByKey().startAt(input).endAt(input+"\uf8ff"); 
citiesQuery.addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     List<String> cities = new ArrayList<String>(); 
     for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { 
      cities.add(postSnapshot.getValue().toString()); 
     } 

通过启动在用户输入并与用户输入开始最后一个字符串结尾,你得到所有符合条件的物品

对于项目的相对短名单瑞安的做法也将正常工作。但上面的Firebase查询将过滤服务器端。

更新

我只是跑这个代码:

DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference("39714936"); 

    String input = "G"; 

    DatabaseReference cities = databaseRef.child("cities"); 
    Query citiesQuery = cities.orderByKey().startAt(input).endAt(input + "\uf8ff"); 
    citiesQuery.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      List<String> cities = new ArrayList<String>(); 

      for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) { 
       cities.add(postSnapshot.getValue().toString()); 
      } 
      System.out.println(cities); 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 

而且它印:

真正

真正

所以CLEA rly匹配两个城市。

随意测试对我的数据库:https://stackoverflow.firebaseio.com/39714936

+0

它正在返回一个空的快照 –

+0

我测试过,它适用于我。我添加了完整的片段和链接到我的数据库的问题。 –

+0

我也测试过它,并且工作正常 –

0

当然,OrderByValue不会返回任何内容,因为这是您拥有的布尔值。

您可以使用startAt和endAt方法来执行此操作。 (以下是火力地堡2.0的代号)

var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs"); 
ref.orderByKey().startAt("b").endAt("b\uf8ff").on("child_added", function(snapshot) { 
    console.log(snapshot.key()); 
}); 

您可以探索更多的火力地堡3文档网站here

瑞安做的是对的。但是,您必须在dataSnapshot上实施startAt以确保您的“实时”搜索有效。

+0

该代码是Android应用程序所需的 –

+0

这就是为什么这是在Android标签? – Nicholas

+0

我不认为你用我的方法startAt,因为我正在执行一个查询,我分配一个实时侦听器来侦听对数据库的任何更改。 – Ryan

1

尝试类似的方法来遍历cities快照中的子项并将所有城市添加到StringsArrayList

ArrayList<String> cityList = new ArrayList<>(); 

databaseRef.child("cities").addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     cityList.clear(); 
     for (DataSnapshot data : dataSnapshot.getChildren()){ 
      cityList.add(data.getKey); 
     } 

    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) { 
     Log.w(TAG, "getUser:onCancelled", databaseError.toException()); 
     // ... 
    } 
}); 

编辑本段为清楚:

这将让你的所有城市读入程序存储器,所以你可以利用这些数据来显示城市的用户。如果城市列表发生变化,用户看到的数据也会变化。如果用户不在线,这将无法工作。这将在数​​据库上放置一个实时的在线唯一监听器。

逻辑在我心中是一样的东西:

  1. 坐落在文本框中输入值听众。
  2. 当用户键入时,使视图显示数组列表 中的所有项目,这些项目以键入的相同子字符串开头。
  3. 当然处理arrayIndex错误。

希望这会让你走上正轨。我相信还有其他方法可以实施,但这是我个人的做法。如果您需要帮助显示正确城市的代码,请与我开始聊天,我可以与您一起集体讨论。

+0

我明白了你的观点,但我想保持“自动完成”功能在线,以便我可以添加或删除城市,而无需在本地存储。 –

+1

它仍然是我在做这件事的方式。不管你做什么,你都必须在某个时间点将一些数据读入变量,否则你的应用程序将无法显示城市名称。它仍然支持在线删除,如果有人在另一个用户正在输入时删除了一个城市,在输入时仍然会更新其他用户列表。我想我可能是在解释听众的错误,或者我只是误解了需求。 – Ryan

+0

我想你的方法是正确的。但是mi的想法是将Firebase发送给一个城市的第一个字母,并且在快照中,只列出以这些字母开头的城市。 –

相关问题