简体   繁体   中英

Flutter: Firebase basic Query or Basic Search code

在此处输入图像描述

The main concept is showing documents or fields which contains the searched alphabet.

The search bar gets the given input, it send to the _firebasesearch() , but in return nothing comes out, and the above image is my database structure, trying to figure out more than a week.

CODE

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_search_bar/flutter_search_bar.dart';

SearchBar searchBar;
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

class DisplayCourse extends StatefulWidget {
  @override
  _DisplayCourseState createState() => new _DisplayCourseState();
}

AppBar _buildAppBar(BuildContext context) {
  return new AppBar(
    title: new Text("FIREBASE QUERY"),
    centerTitle: true,
    actions: <Widget>[
      searchBar.getSearchAction(context),
    ],
  );
}

class _DisplayCourseState extends State<DisplayCourse> {
  String _queryText;

  _DisplayCourseState() {
    searchBar = new SearchBar(
      onSubmitted: onSubmitted,
      inBar: true,
      buildDefaultAppBar: _buildAppBar,
      setState: setState,
    );
  }

  void onSubmitted(String value) {
    setState(() {
      _queryText = value;
      _scaffoldKey.currentState.showSnackBar(new SnackBar(
        content: new Text('You have Searched something!'),
        backgroundColor: Colors.yellow,
      ));
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _scaffoldKey,
      appBar: searchBar.build(context),
      backgroundColor: Colors.red,
      body: _fireSearch(_queryText),
    );
  }
}

Widget _fireSearch(String queryText) {
  return new StreamBuilder(
    stream: Firestore.instance
    .collection('courses')
    .where('title', isEqualTo: queryText)
    .snapshots(),
    builder: (context, snapshot) {
      if (!snapshot.hasData) return new Text('Loading...');
      return new ListView.builder(
        itemCount: snapshot.data.documents.length,
        itemBuilder: (context, index) =>
            _buildListItem(snapshot.data.documents[index]),
      );
    },
  );
}

Widget _buildListItem(DocumentSnapshot document) {
  return new ListTile(
    title: document['title'],
    subtitle: document['subtitle'],
  );
}

the main concept is showing document sor fields which contains the searched alphabet

the search bar gets the given input, it send to the _firebasesearch(),but in return nothing comes out, and the above image is my database structure, trying to figure out more than a week,

I'm a bit too late but I just want to share something on how I implement the search function without using third party app in my case. My solution is a bit straight forward querying using firestore. Here's the code:

Future<List<DocumentSnapshot>> getSuggestion(String suggestion) =>
  Firestore.instance
      .collection('your-collection')
      .orderBy('your-document')
      .startAt([searchkey])
      .endAt([searchkey + '\uf8ff'])
      .getDocuments()
      .then((snapshot) {
        return snapshot.documents;
      });

example if you want to search all keywords containing "ab" then it will display all words containing "ab" (ex. abcd, abde, abwe). If you want to make auto suggest search function you can use typehead. which can be found in this link: https://pub.dev/packages/flutter_typeahead

Good luck.

This might sound a ridiculous solution but actually works so well, It's almost like the Like '%' query from SQL

In the TextField as you type a value the inside where() isGreaterThanOrEqualTowill compare it and all the string values greater than the input and If you concatinate a 'Z' At the end then isLessThan will end just after your search keyword and You get the desired Result from firestore.

// Declare your searchkey and Stream variables first
String searchKey;
Stream streamQuery;

TextField(
              onChanged: (value){
                  setState(() {
                    searchKey = value;
                    streamQuery = _firestore.collection('Col-Name')
                        .where('fieldName', isGreaterThanOrEqualTo: searchKey)
                        .where('fieldName', isLessThan: searchKey +'z')
                        .snapshots();
                  });
    }),

I used this Stream in StreamBuilder and It works exactly as expected.

Limitations:

  1. The search is case sensitive(You can convert searchKey to specific case if your data is consistent like Type Case )
  2. You have to start searching from the first letter, it can't search from mid

You don't have to rebuild your whole stream, just filter the results from your stream depending on your search string. Fast, does not need to rebuild the whole stream, finds occurences of the search string not only from the start of a word and is case-insensitive.

return StreamBuilder(
  stream: FirebaseFirestore.instance.collection("shops").snapshots(),
  builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {

    if (snapshot.hasError)  // TODO: show alert
      return Text('Something went wrong');

    if (snapshot.connectionState == ConnectionState.waiting)
      return Column(
        children: [
          Center(
              child: CupertinoActivityIndicator()
          )
        ],
      );

    var len = snapshot.data.docs.length;
    if(len == 0)
      return Column(
        children: [
          SizedBox(height: 100),
          Center(
            child: Text("No shops available", style: TextStyle(fontSize: 20, color: Colors.grey)),
          )
        ],
      );

    List<Shop> shops = snapshot.data.docs.map((doc) => Shop(
        shopID: doc['shopID'],
        name: doc['name'],
        ...
    )).toList();
    shops = shops.where((s) => s.name.toLowerCase().contains(searchString.text.toLowerCase())).toList();
    
    
    return
        Expanded(
          child: ListView.builder(
              padding: EdgeInsets.symmetric(vertical: 15),
              scrollDirection: Axis.vertical,
              shrinkWrap: true,
              itemCount: shops.length,
              itemBuilder: (context, index) {
                return shopRow(shops[index]);
              }
          ),
        );
  },
);

The issue is you are expecting results from firestore where title is equal to queryText not title contains queryText .

If you want the search feature, you can get and store the firestore documents in a variable something like List<Model> model instead of StreamBuilder and implement search manually from the above stored list of model.

THIS IS ANOTHER SEARCH CODE THIS WILL SEARCH INSIDE FIREBASE DATABASE

截屏

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';

class Db extends StatefulWidget {
  @override
  HomeState createState() => HomeState();
}

class HomeState extends State<Db> {
  List<Item> Remedios = List();
  Item item;
  DatabaseReference itemRef;
  TextEditingController controller = new TextEditingController();
  String filter;

  final GlobalKey<FormState> formKey = GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    item = Item("", "");
    final FirebaseDatabase database = FirebaseDatabase.instance; //Rather then just writing FirebaseDatabase(), get the instance.
    itemRef = database.reference().child('Remedios');
    itemRef.onChildAdded.listen(_onEntryAdded);
    itemRef.onChildChanged.listen(_onEntryChanged);
    controller.addListener(() {
  setState(() {
    filter = controller.text;
  });
});
  }

  _onEntryAdded(Event event) {
    setState(() {
      Remedios.add(Item.fromSnapshot(event.snapshot));
    });
  }

  _onEntryChanged(Event event) {
    var old = Remedios.singleWhere((entry) {
      return entry.key == event.snapshot.key;
    });
    setState(() {
      Remedios\[Remedios.indexOf(old)\] = Item.fromSnapshot(event.snapshot);
    });
  }

  void handleSubmit() {
    final FormState form = formKey.currentState;

    if (form.validate()) {
      form.save();
      form.reset();
      itemRef.push().set(item.toJson());
    }
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        centerTitle: true,
        backgroundColor: new Color(0xFFE1564B),
      ),
      resizeToAvoidBottomPadding: false,
      body: Column(
        children: <Widget>\[
          new TextField(
          decoration: new InputDecoration(
          labelText: "Type something"
          ),
          controller: controller,
          ),
          Flexible(
            child: FirebaseAnimatedList(
              query: itemRef,
              itemBuilder: (BuildContext context, DataSnapshot snapshot,
                  Animation<double> animation, int index) {
                return  Remedios\[index\].name.contains(filter) || Remedios\[index\].form.contains(filter) ? ListTile(
                  leading: Icon(Icons.message),
                  title: Text(Remedios\[index\].name),
                  subtitle: Text(Remedios\[index\].form),
                ) : new Container();
              },
            ),
          ),
        \],
      ),
    );
  }
}

class Item {
  String key;
  String form;
  String name;

  Item(this.form, this.name);

  Item.fromSnapshot(DataSnapshot snapshot)
      : key = snapshot.key,
        form = snapshot.value\["form"\],
        name = snapshot.value\["name"\];

  toJson() {
    return {
      "form": form,
      "name": name,
    };
  }
}

The solution that i found:

List<String> listaProcura = List();
    String temp = "";
    for(var i=0;i<nomeProduto.length; i++) {
      if(nomeProduto[i] == " ") {
        temp = "";
      } else {
        temp = temp + nomeProduto[i];
        listaProcura.add(temp);
      }
    }

The "listaProcura" is the name of the list. the String "temp" is the name of a temporary string. This way you will save this list of names in the firebase database. Will be like:

  [0] E
  [1] Ex
  [2] Exa
  [3] Exam
  [4] Examp
  [5] Exampl
  [6] Example
  [7] o
  [8] on
  [9] one

For retrieving this info with the word you wanna search:

await Firestore.instance.collection('name of your collection').where('name of your list saved in the firebase', arrayContains: 'the name you are searching').getDocuments();

This way if you search for "one" and the name is "Example one" the search will return properly.

if Search list is case senstive like this :

  1. Curaprox Be You Display
  2. Curaprox Black is White Display
  3. Curaprox Black is White Mini Display
  4. Curaprox Hydrosonic Pro Display
  5. Curaprox Large Interdental Brush Display

then :

                response = await FirebaseFirestore.instance
                .collection('pointOFSale')
                .orderBy("title")
                .startAt([val.capitalize()]).endAt(
                    [val[0].toUpperCase() + '\uf8ff']).get();

Extension code :

          extension StringExtension on String {
        String capitalize() {
          return "${this[0].toUpperCase()}${this.substring(1)}";
        }
      }

if List is like :

  1. curaprox be you display
  2. curaprox black is white display
  3. curaprox black is white mini display

then :

                response = await FirebaseFirestore.instance
                .collection('pointOFSale')
                .orderBy("title")
                .startAt([val]).endAt([val + '\uf8ff']).get();

You can use https://pub.dev/packages/firestore_search package, with less code and more efficiency.

soo simple and fast.

if (text.length > 1) {
  setState(() {
    tempSearchStore = _listPkh.documents.where((d) {
      if (d['nama'].toLowerCase().indexOf(text) > -1) {
        return true;
      } else if (d['alamat'].toLowerCase().indexOf(text) > -1) {
        return true;
      }
      return false;
    }).toList();
  });
} else {
  setState(() {
    tempSearchStore = _listPkh.documents;
  });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM