2016-09-27 17 views
5

FirebaseとNoSQLを初めて使用しました。私はアンドロイドのデモを持っています。市のオートコンプリートテキストフィールドには、入力中にFirebase DBから持っている都市を設定したいと思っています。AndroidでFirebase Realtime Databaseからデータを取得する

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

これは私がこれまで行ってきたことです。

文字列(キーボードからの入力)で始まるDB都市を検索するにはどうすればよいですか?私が "G"と打ち始めると、 "Guayaquil"と "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) { 

     } 
    }); 

そして:

だから、クレアをrlyは2つの都市に一致します。

は私のデータベースに対してテストしてお気軽に:https://stackoverflow.firebaseio.com/39714936

+0

空のスナップショット –

+0

が返されています。私はそれをテストしてくれました。私は完全なスニペットと私のデータベースへのリンクを質問に追加しました。 –

+0

私もそれをテストし、完全に動作しています –

0

もちろん、OrderByValueはあなたが持っているブーリアンなので何も返しません。

startAtメソッドとendAtメソッドを使用してこれを行うことができます。あなたがFirebase 3ドキュメントサイトhereの詳細を探索することができます

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()); 
}); 

(以下Firebase 2.0のコードです)。

ライアン氏は正しいと思いました。ただし、 "ライブ"検索が確実に動作するように、dataSnapshotにstartAtを実装する必要があります。

+0

Android Appのコードが必要です –

+0

これがAndroidでタグ付けされている理由は何ですか? – Nicholas

+0

私は自分のメソッドでstartAtを使うと思いません。なぜなら、私はクエリを実行しているからです。リアルタイムリスナーを割り当てて、データベースの変更を待ちます。 – Ryan

1

citiesスナップショットで子どもを繰り返して、すべての都市をArrayListStringsに追加してください。

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

あなたのアプローチが正しいと思います。しかし、ミアのアイデアはFirebaseに都市の最初の文字を送り、Snapshotにはそれらの文字で始まる都市だけがリストアップされました。 –

関連する問題