Flutter: базовый запрос Firebase или базовый поисковый код

введите описание изображения здесь

Основная концепция - отображение полей документа, содержащего искомый алфавит.

Панель поиска получает заданный ввод, он отправляется в _firebasesearch(), но взамен ничего не выходит, а приведенное выше изображение - это моя структура базы данных, пытающаяся выяснить больше, чем за неделю.

КОД

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'],
  );
}

основная концепция - отображение полей документа, содержащих искомый алфавит

панель поиска получает заданный ввод, он отправляется в _firebasesearch (), но при повторном запуске ничего не выходит, а приведенное выше изображение - это моя структура базы данных, пытаясь вычислить более недели,


comment
Правильное форматирование кода повышает вероятность того, что кто-то действительно попытается его понять. Не должно быть слишком сложно.   -  person Günter Zöchbauer    schedule 15.06.2018
comment
Предоставляете ли вы полный заголовок в строке поиска, например new program, или только его часть?   -  person Vinoth Kumar    schedule 15.06.2018
comment
@VinothKumar нового хватит, братан, я не буду искать по всему тексту   -  person Rajesh Jr.    schedule 15.06.2018
comment
@VinothKumar, я не мог понять, братан, просто новичок   -  person Rajesh Jr.    schedule 15.06.2018
comment
Я не думаю, что сейчас мы можем запрашивать часть текста   -  person Vinoth Kumar    schedule 15.06.2018
comment
@VinothKumar, я жду вот этого stackoverflow.com/questions/46912713/   -  person Rajesh Jr.    schedule 15.06.2018
comment
К сожалению, я не думаю, что сейчас это возможно в пожарном магазине.   -  person Vinoth Kumar    schedule 15.06.2018
comment
@VinothKumar, спасибо за ваш вклад, я получил код от моей группы флаттера в facebook, пожалуйста, взгляните на него, который может быть вам полезен в будущем.   -  person Rajesh Jr.    schedule 17.06.2018
comment
@ GünterZöchbauer, спасибо, я нашел ответ от группы флаттера на fb   -  person Rajesh Jr.    schedule 17.06.2018


Ответы (7)


Я немного опоздал, но я просто хочу поделиться кое-чем о том, как я реализую функцию поиска без использования стороннего приложения в моем случае. Мое решение - это немного прямолинейный запрос с использованием хранилища огня. Вот код:

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

Например, если вы хотите выполнить поиск по всем ключевым словам, содержащим «ab», то он отобразит все слова, содержащие «ab» (например, abcd, abde, abwe). Если вы хотите, чтобы функция поиска предлагалась автоматически, вы можете использовать шрифт. который можно найти по этой ссылке: https://pub.dev/packages/flutter_typeahead

Удачи.

person J.John    schedule 25.06.2019
comment
Можем ли мы сделать регистр нечувствительным? - person Mahi; 26.03.2020
comment
Привет @Mahi, на данный момент мое текущее решение - автоматически строчить сохраненный текст и автоматически строчить форму поиска. пример. ключевое слово: "Хлеб", затем автоматически добавляется для другого поля "хлеб", которое будет использоваться для поиска по ключу. - person J.John; 13.04.2020
comment
я тоже делаю то же самое, что и сейчас. Любая идея, будет ли firebase когда-либо поддерживать эту функциональность, потому что я думаю, что у mongoDB она есть. - person Mahi; 15.04.2020

Это может показаться нелепым решением, но на самом деле работает так хорошо. Это почти как запрос Like '%' из SQL.

В текстовом поле при вводе значения внутри where () isGreaterThanOrEqualTowill сравнивает его и все строковые значения, превышающие ввод, и если вы ставите букву Z в конце, то isLessThan закончится сразу после вашего ключевого слова поиска, и вы получите желаемый результат от 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();
                  });
    }),

Я использовал этот поток в StreamBuilder, и он работает точно так, как ожидалось.

Ограничения:

  1. Поиск чувствителен к регистру (вы можете преобразовать searchKey в конкретный регистр, если ваши данные согласованы, например, Type Case).
  2. Вы должны начать поиск с первой буквы, он не может искать с середины
person Mahi    schedule 26.03.2020
comment
Чувак, я пытаюсь понять это уже около недели, и я не могу никакими словами описать, насколько ты классный, чтобы понять это - person James 666; 28.09.2020
comment
@ James666, спасибо, очень рад, что смог помочь. Именно такие комментарии побуждают нас делиться еще и еще. Надеюсь, вы проголосовали за и поделитесь своими знаниями с сообществом. - person Mahi; 30.09.2020

Вам не нужно перестраивать весь поток, просто отфильтруйте результаты из потока в зависимости от строки поиска. Быстро, не нужно перестраивать весь поток, находит вхождения строки поиска не только с начала слова и без учета регистра.

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]);
              }
          ),
        );
  },
);
person Lukas Roh    schedule 27.03.2021

Проблема в том, что вы ожидаете результатов от firestore, где title is equal to queryText не title contains queryText.

Если вам нужна функция поиска, вы можете get and store the firestore documents в переменной типа List<Model> model вместо StreamBuilder и implement search manually из приведенного выше сохраненного списка моделей.

person Vinoth Kumar    schedule 15.06.2018

ЭТО ДРУГОЙ ПОИСКОВЫЙ КОД, ЭТО БУДЕТ ИСКАТЬ В БАЗЕ ДАННЫХ FIREBASE

Снимок экрана

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,
    };
  }
}
person Rajesh Jr.    schedule 21.06.2018
comment
не могли бы вы поделиться репозиторием на github, чтобы мы могли клонировать код и запустить его? - person biniam; 15.03.2019
comment
@biniam Извините, это был мой старый пост, и вышеупомянутый метод настолько глуп, что firebase / firestore не предназначены для поиска, и, черт возьми, я сделал выше, извлек все дочерние элементы внутри ребенка и показал только конкретный документ, который содержит ключевое слово tyepd, [Я НЕ РЕКОМЕНДУЮ СПОСОБ НА СЕЙЧАС] извините !! - person Rajesh Jr.; 16.03.2019
comment
@biniam на данный момент нет подходящего текстового поиска для firestore и firebase, но вы можете использовать Algolia, посмотрите руководства на канале RajaYogan Youtube ›youtube.com/channel/UCjBxAm226XZvgrkO-JyjJgQ (или) канал Samrath agarwal на YouTube ›youtube.com/channel/UCDXWrSUyXN47WOF0Ih5AjIg - person Rajesh Jr.; 18.03.2019
comment
gist.github.com/haidar786/eb2d39251b21ed8249abee06641452c6 search - person Hussnain Haidar; 05.10.2019
comment
@HussnainHaidar его инструмент старый пост и сам поиск еще не реализован, кстати, метод, который вы предоставили, полностью убивает платежи. - person Rajesh Jr.; 07.10.2019

Решение, которое я нашел:

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

ListaProcura - это имя списка. String temp - это имя временной строки. Таким образом вы сохраните этот список имен в базе данных firebase. Будет как:

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

Чтобы получить эту информацию по слову, которое вы хотите найти:

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

Таким образом, если вы ищете один и его имя - Пример 1, поиск вернется правильно.

person lukeluciano3    schedule 27.06.2020

так просто и быстро.

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;
  });
}
person Mr Hafid    schedule 20.03.2020