简体   繁体   中英

flutter dynamic query Firebase Firestore

I am creating a view where the user can select several elements. Then by doing an onTap on a button, this should generate the query and display the results of the query on an other view. My challenges are to make sure that I am getting all the criterias choosen by the user and then to build query with multiple field values.

Should I do one query and then a query on that query etc...? Thank you

Right now, when I am doing several Where, the query returns records that should not been returned. Not sure why. Please, can you help? Many thanks.

I am attaching a screenshot of the view.

在此处输入图像描述

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
import 'package:my_gtd_20220804/Constante/Const.dart';
import 'engage_display_result_search.dart';

//######################
List <dynamic> _statusSelected2 =[];
//######################

String? _timeSelectedPicker = '';
String? _energySelectedPicker = '';
String _importantSelectedPicker = '';
String _urgentSelectedPicker = '';

int valuePickerTimeSelected =0;
int valuePickerEnergySelected =0;
int valuePickerImportantSelected =0;
int valuePickerUrgentSelected =0;


List <MultiSelectItem<dynamic>>_allContexts=[];
List <dynamic> _contextSelected = [];
List <MultiSelectItem<dynamic>>result=[];
List<Status?> _statusSelected =[];

List<String> contextWhere=[];
List<String> importantWhere =[];
List<String> urgentWere =[];
final _multiSelectKeyContext = GlobalKey<FormFieldState>();
final _multiSelectKeyStatus = GlobalKey<FormFieldState>();

class Status {
  final int id;
  final String name;
  Status({
    required this.id,
    required this.name,
  });
}

class EngagePage extends StatefulWidget {
  const EngagePage({ Key? key, }):super(key:key);
  // final String title;
  @override
  _EngagePageState createState() => _EngagePageState();
}

class _EngagePageState extends State<EngagePage> {

  static final List<MultiSelectItem<dynamic>> _context = [];
  static final List<Status> _status = [
    Status(id: 1, name: "Scheduled for"),
    Status(id: 2, name: "Waiting for"),
  ];

  final _itemsStatus = _status
      .map((status) => MultiSelectItem<Status>(status, status.name))
      .toList();

List <MultiSelectItem<dynamic>>allContexts=[];
  @override
  void initState() {
    _contextSelected = _context;
    _statusSelected = _status;
    getAllContextInFirebaseV1().then(( List<dynamic> testallContexts) {

    setState(() {
      allContexts=testallContexts.map((e) => MultiSelectItem(e, e)).toList();
    });
    });
    super.initState();
  }

  Future <List<dynamic>>  getAllContextInFirebaseV1() async {
    CollectionReference ref = FirebaseFirestore.instance.collection('Users')
        .doc((FirebaseAuth.instance.currentUser!.uid))
        .collection('contexts');

    QuerySnapshot contextsQuery = await ref.get();
    final allContexts = contextsQuery.docs.map((snap) => (snap.data() as Map<String, dynamic>)['context_Name']).toList();
    return allContexts; //List<MultiSelectItem<dynamic>>;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: const Text('ENGAGE'),
            actions: <Widget>[
              Padding(
                  padding: const EdgeInsets.only(right: 20.0),
                  child: GestureDetector(
                    onTap: () async {

                      await BuildQueryResearch();
                      search();
                    },
                    child: const Icon(
                      Icons.search,
                      size: 26.0,
                    ),
                  )
              ),
            ]
        ),
        backgroundColor: Colors.white,
        body: SingleChildScrollView(

            child: Column(
                children: <Widget>[

                  const SizedBox(height: 10),
                  MultiSelectBottomSheetField(
                    key: _multiSelectKeyContext,
                    initialChildSize: 0.7,
                    maxChildSize: 0.95,
                    title: const Text("Context", style: TextStyle(fontSize: 19),),
                    buttonText: const Text(
                      "Context", style: TextStyle(fontSize: 19),),
                    searchTextStyle: const TextStyle(fontSize: 19),
                    searchHintStyle: const TextStyle(fontSize: 19),
                    itemsTextStyle: const TextStyle(fontSize: 19),
                    items: allContexts,
                    searchable: true,
                    onConfirm: (valueContext) {
                      setState(() {
                        _contextSelected = valueContext;
                      });
                      _multiSelectKeyContext.currentState!.validate();

                    },
                    chipDisplay: MultiSelectChipDisplay(
                      textStyle: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold,fontSize: 19),
                      onTap: (dynamic item) {
                        setState(() {
                       });
                        _multiSelectKeyContext.currentState!.validate();
                      },
                    ),
                  ),

                  const SizedBox(height: 40),

//MultiSelect For Status
                  MultiSelectBottomSheetField<Status?>(
                    key: _multiSelectKeyStatus,
                    initialChildSize: 0.7,
                    maxChildSize: 0.95,
                    title: const Text("Status", style: TextStyle(fontSize: 19),),
                    buttonText: const Text("Status", style: TextStyle(fontSize: 19),),
                    searchTextStyle: const TextStyle(fontSize: 19),
                    searchHintStyle: const TextStyle(fontSize: 19),
                    itemsTextStyle: const TextStyle(fontSize: 19),
                    items: _itemsStatus,
                    searchable: true,
                    onConfirm: (values2) {
                      setState(() {
                        _statusSelected = values2 ;
                        _statusSelected2.add(values2);
                      });
                      _multiSelectKeyStatus.currentState?.validate();
                    },
                    chipDisplay: MultiSelectChipDisplay(
                      textStyle: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold,fontSize: 19),
                      onTap: (item) {
                        setState(() {
                     //     _statusSelected.remove(item);
                        });
                        _multiSelectKeyStatus.currentState!.validate();
                      },
                    ),
                  ),
                  const SizedBox(height: 40),

//######### Energy & Time / Important /urgent
                  Card(
                      child:
                      Container(

                        alignment: Alignment.center,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            //Time
                            FlatButton(
                              onPressed: () {},
                              child:
                              InkWell(
                                child: Container(
                                  //  color: Colors.white,
                                    child: Column(
                                        mainAxisAlignment: MainAxisAlignment
                                            .center,
                                        children: [

                                          if (_timeSelectedPicker!.length <
                                              2 )...[
                                            const Icon(Icons.timer),
                                            const Text('Time', style: TextStyle(
                                              color: Colors.black,))
                                          ]
                                          else
                                            ...[
                                              const Icon(Icons.timer),
                                              Text(_timeSelectedPicker!,
                                                  style: const TextStyle(
                                                    color: Colors.black,))
                                            ],
                                        ]
                                    )
                                ),
                                onTap: () {
                                  _showPickerTime(context, TimeList);
                                },
                              ),
                            ),

                            //Energy
                            FlatButton(
                              onPressed: () {},
                              child:
                              InkWell(
                                child: Container(
                                  //   color: Colors.white,
                                    child: Column(
                                      mainAxisAlignment: MainAxisAlignment.center,
                                      children: [

                                        if (_energySelectedPicker!.length <
                                            2 )...[
                                          const Icon(Icons.battery_charging_full,
                                            color: Colors.black,),
                                          const Text('Energy', style: TextStyle(
                                            color: Colors.black,))
                                        ]
                                        else
                                          ...[
                                            const Icon(Icons.battery_charging_full,
                                              color: Colors.black,),
                                            Text(_energySelectedPicker!,
                                                style: const TextStyle(
                                                  color: Colors.black,))
                                          ],
                                      ],
                                    )
                                ),
                                onTap: () {
                                  _showPickerEnergy(context, energyList);
                                },
                              ),
                            ),

                            //Important
                            FlatButton(
                              onPressed: () {},
                              child:
                              InkWell(
                                child: Container(
                                  //   color: Colors.white,
                                    child: Column(
                                        mainAxisAlignment: MainAxisAlignment
                                            .center,
                                        children: [

                                          if (_importantSelectedPicker ==
                                              '' )...[
                                            const Icon(Icons.star_border,
                                              color: Colors.black,),
                                            const Text('Important?', style: TextStyle(
                                              color: Colors.black,))
                                          ],

                                          if (_importantSelectedPicker ==
                                              'Not Important' )...[
                                            const Icon(Icons.star_border,
                                              color: Colors.black,),
                                            const Text('Not Important',
                                                style: TextStyle(
                                                  color: Colors.black,))
                                          ],

                                          if (_importantSelectedPicker ==
                                              'All' )...[
                                            const Icon(Icons.star_border,
                                              color: Colors.orange,),
                                            const Text('All', style: TextStyle(
                                              color: Colors.black,))
                                          ],

                                          if (_importantSelectedPicker ==
                                              'Important' )...[
                                            const Icon(Icons.star,
                                              color: Colors.orange,),
                                            const Text('Important', style: TextStyle(
                                              color: Colors.black,))
                                          ]
                                        ]
                                    )),

                                onTap: () {
                                  _showPickerImportant(context, importantList);
                                },
                              ),
                            ),

                            //Urgent
                            FlatButton(
                              onPressed: () {},
                              child:
                              InkWell(
                                child: Container(
                                  //   color: Colors.white,
                                    child: Column(
                                      mainAxisAlignment: MainAxisAlignment
                                          .center,
                                      children: [

                                        if (_urgentSelectedPicker == '' )...[
                                          const Icon(Icons.outlined_flag,
                                            color: Colors.black,),
                                          const Text('Urgent?', style: TextStyle(
                                            color: Colors.black,))
                                        ],

                                        if (_urgentSelectedPicker ==
                                            'Not Urgent' )...[
                                          const Icon(Icons.outlined_flag,
                                            color: Colors.black,),
                                          const Text('Not Urgent', style: TextStyle(
                                            color: Colors.black,))
                                        ],

                                        if (_urgentSelectedPicker ==
                                            'All' )...[
                                          const Icon(Icons.outlined_flag,
                                            color: Colors.orange,),
                                          const Text('All', style: TextStyle(
                                            color: Colors.black,))
                                        ],

                                        if (_urgentSelectedPicker ==
                                            'Urgent' )...[
                                          const Icon(Icons.flag, color: Colors.red,),
                                          Text(_urgentSelectedPicker,
                                              style: const TextStyle(
                                                color: Colors.black,))
                                        ]
                                      ],
                                    )
                                ),
                                onTap: () {
                                  _showPickerUrgent(context, urgentList);
                                  setState(() {
                                  });
                                },
                              ),
                            ),
                          ],
                        ),

                      )),

                  const SizedBox(height: 40),

                  Container(height: 200,),

                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      ElevatedButton(child:
                      const Text('CANCEL'),
                          onPressed: () {
                            getAllContextInFirebaseV1();

                            // Navigator.pop(context);
                          }
                      ),
                      ElevatedButton(child:
                      const Text('FIND'),
                          onPressed: () async {

                        //   await BuildQueryResearch();
                           await search();

                            Navigator.push(
                                context,
                                MaterialPageRoute(
                                builder: (context) =>
                            Engage_Display_Results(contextWhere,importantWhere,urgentWere)));
                          }
                      ),
                    ],
                  ),
                ])));
  }

  void _showPickerImportant(BuildContext ctx, List myListImportant) {
    showCupertinoModalPopup(
        context: ctx,
        builder: (_) =>
            Column(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Container(
                    decoration: const BoxDecoration(
                      color: Color(0xffffffff),
                      border: Border(
                        bottom: BorderSide(
                          color: Color(0xff999999),
                          width: 0.0,
                        ),
                      ),
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        CupertinoButton(
                          onPressed: () {
                            Navigator.of(context).pop(_showPickerImportant);
                          },
                          padding: const EdgeInsets.symmetric(
                            horizontal: 16.0,
                            vertical: 5.0,
                          ),
                          child: const Text('Cancel'),
                        ),


                        const DefaultTextStyle(
                          style: TextStyle(fontSize: 16.0,
                              color: Colors.black,
                              fontWeight: FontWeight.bold),
                          child: Text('Time Needed'),
                        ),

                        // Text('Energy Needed', style: TextStyle(fontSize: 12.0, color: Colors.black),
                        // ),

                        CupertinoButton(
                          onPressed: () {
                            setState(() {
                              // valuePickerEnergySelected = value;
                              _importantSelectedPicker =
                              importantList[valuePickerImportantSelected];
                            });
                            _importantSelectedPicker =
                            importantList[valuePickerImportantSelected];

                            Navigator.of(context).pop(_showPickerImportant);
                          },
                          padding: const EdgeInsets.symmetric(
                            horizontal: 16.0,
                            vertical: 5.0,
                          ),
                          child: const Text('Confirm'),
                        ),
                      ],
                    ),
                  ),

                  Container(
                    //width: 360,
                    height: 250,
                    decoration: const BoxDecoration(
                      borderRadius: BorderRadius.all(Radius.circular(15.0)),
                    ),

                    child: CupertinoTheme(
                        data: const CupertinoThemeData(
                            textTheme: CupertinoTextThemeData(
                              //  dateTimePickerTextStyle: TextStyle(color: Colors.blue, fontSize: 16),
                              // pickerTextStyle: TextStyle(color: Colors.green, fontSize: 12
                              //   )
                            )),

                        child: CupertinoPicker(
                          backgroundColor: Colors.white,
                          itemExtent: 30,
                          scrollController: FixedExtentScrollController(
                              initialItem: myListImportant.indexOf(
                                  _importantSelectedPicker)),
                          useMagnifier: true,
                          magnification: 1.3,

                          children: [
                            for (String name in myListImportant) Center(
                                child: Text(name)),
                          ],
                          onSelectedItemChanged: (value) {
                            setState(() {
                              valuePickerImportantSelected = value;
                            });
                          },
                        )
                    ),
                  ),
                ]

            ));
  }

  void _showPickerUrgent(BuildContext ctx, List myListUrgent) {
    showCupertinoModalPopup(
        context: ctx,
        builder: (_) =>
            Column(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Container(
                    decoration: const BoxDecoration(
                      color: Color(0xffffffff),
                      border: Border(
                        bottom: BorderSide(
                          color: Color(0xff999999),
                          width: 0.0,
                        ),
                      ),
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        CupertinoButton(
                          onPressed: () {
                            Navigator.of(context).pop(_showPickerTime);
                          },
                          padding: const EdgeInsets.symmetric(
                            horizontal: 16.0,
                            vertical: 5.0,
                          ),
                          child: const Text('Cancel'),
                        ),


                        const DefaultTextStyle(
                          style: TextStyle(fontSize: 16.0,
                              color: Colors.black,
                              fontWeight: FontWeight.bold),
                          child: Text('Urgent?'),
                        ),

                        // Text('Energy Needed', style: TextStyle(fontSize: 12.0, color: Colors.black),
                        // ),

                        CupertinoButton(
                          onPressed: () {
                            setState(() {
                              // valuePickerEnergySelected = value;
                              _urgentSelectedPicker =
                              myListUrgent[valuePickerUrgentSelected];
                            });
                            _urgentSelectedPicker =
                            myListUrgent[valuePickerUrgentSelected];

                            Navigator.of(context).pop(_showPickerUrgent);
                          },
                          padding: const EdgeInsets.symmetric(
                            horizontal: 16.0,
                            vertical: 5.0,
                          ),
                          child: const Text('Confirm'),
                        ),
                      ],
                    ),
                  ),

                  Container(
                    //width: 360,
                    height: 250,
                    decoration: const BoxDecoration(
                      borderRadius: BorderRadius.all(Radius.circular(15.0)),
                    ),

                    child: CupertinoTheme(
                        data: const CupertinoThemeData(
                            textTheme: CupertinoTextThemeData(
                              //  dateTimePickerTextStyle: TextStyle(color: Colors.blue, fontSize: 16),
                              // pickerTextStyle: TextStyle(color: Colors.green, fontSize: 12
                              //   )
                            )),

                        child: CupertinoPicker(
                          backgroundColor: Colors.white,
                          itemExtent: 30,
                          scrollController: FixedExtentScrollController(
                              initialItem: urgentList.indexOf(
                                  _urgentSelectedPicker)),
                          useMagnifier: true,
                          magnification: 1.3,

                          children: [
                            for (String name in myListUrgent) Center(
                                child: Text(name)),
                          ],
                          onSelectedItemChanged: (value) {
                            setState(() {
                              valuePickerUrgentSelected = value;
                            });
                          },
                        )
                    ),
                  ),
                ]
            ));
  }

  Future <void> search() async{

    if (_contextSelected.isEmpty ){

      //TODO SHOW DIALOG
      return;
    }
    else
    {

    }
  }
}

body:  Column(
        //mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Flexible(
            child: StreamBuilder(
                stream: FirebaseFirestore.instance
                    .collection('Users')
                    .doc(FirebaseAuth.instance.currentUser!.uid)
                    .collection('allTasks')
                    .where('task_Context', arrayContainsAny: whereQueryContext)
                    .where('Important', arrayContainsAny: whereQueryImportant)
                    .where('Urgent', arrayContainsAny: whereQueryUrgent)
                    .snapshots(),

                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> snapshot) {
                  if (!snapshot.hasData) {
                    return const Center(
                      child: CircularProgressIndicator(),
                    );
                  }
                  else {

                    return Container(
                      height: MediaQuery.of(context).size.height * .78,
                      width: MediaQuery.of(context).size.width,
                      child: ListView(
                        children: snapshot.data!.docs.map((document) {
                          return Card(
                            child: Text(document['task_Name']),
                          );
                        }).toList(),
                      ),
                    );
                  }
                }),
          ),
        ],
      ),

You need add as many where queries as many criteria you have.

baseQuery.where('field', isEqualTo:'value')  -> this is a new query
         .where('field2', isEqualTo: 'value2)
         .get();

So let's say you have String as key and value:

Query<Map<String, dynamic>> query = baseQueryFromYourCollection;
for(int i=0;i<keyAndValues.length;++i){
   final YourKeyValueClass keyValue =  keyAndValues[i];
   final String key = keyValue.key;
   final String value = keyValue.value; 
   query = query.where(key, isEqualsTo: value); // you need to reassign the query
}

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