在Flutter中使用Firebase Firestore的动态查询

huangapple go评论73阅读模式
英文:

dynamial query in firebase firestore in flutter

问题

I am trying to dynamical query in firestore for <= and >= operator.
that is mean I wanna add each key and value dynamical to the query
but I getting an error that it will not work on firebase.

> All where filters with an inequality (<, <=, >, or >=) must be on the same field. But you have inequality filters on 'FieldPath([price])' and 'FieldPath([meter])'.
'package:cloud_firestore/src/query.dart':
Failed assertion: line 780 pos 13: 'hasInequality == field'

My code:

class HomePage extends StatefulWidget {

  @override
  _HomePageState createState() =&gt; _HomePageState();
}

class _HomePageState extends State&lt;HomePage&gt; {
  late Query _query;
  final Map&lt;String, dynamic&gt; _filters = {
    &#39;price&#39;: 500,
    &#39;meter&#39;: 120,
  };
@override
  void initState() {
    super.initState();
    _query = FirebaseFirestore.instance.collection(&#39;items&#39;);
    for (var key in _filters.keys) {
      if (_filters[key] != null) {
        _query = _query.where(key, isGreaterThanOrEqualTo: _filters[key]);
      }
    }
  }
@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(&#39;My App&#39;),
      ),
      body: StreamBuilder&lt;QuerySnapshot&gt;(
        stream: _query.snapshots(),
        builder: (BuildContext context, AsyncSnapshot&lt;QuerySnapshot&gt; snapshot) {
          if (!snapshot has Data) {
            return const CircularProgressIndicator();
          }
          List&lt;DocumentSnapshot&gt; documents = snapshot data!.docs;
          return ListView.builder(
            itemCount: documents.length,
            itemBuilder: (BuildContext context, int index) {
              DocumentSnapshot document = documents[index];
              return ListTile(
                title: Text(&#39;${document[&#39;price&#39;]}&#39;),
                subtitle: Text(
                    &#39;${document[&#39;meter&#39;]} m&#178; / ${document[&#39;landMeter&#39;]} m&#178;&#39;),
              );
            },
          );
        },
      ),
    );
  }
}

is there any way to work around this limitation?
or dynamic querying?

英文:

I am trying to dynamical query in firestore for <= and >= operator.
that is mean I wanna add each key and value dynamical to the query
but I getting an error that it will not work on firebase.

> All where filters with an inequality (<, <=, >, or >=) must be on the same field. But you have inequality filters on 'FieldPath([price])' and 'FieldPath([meter])'.
'package:cloud_firestore/src/query.dart':
Failed assertion: line 780 pos 13: 'hasInequality == field'

My code:

class HomePage extends StatefulWidget {

  @override
  _HomePageState createState() =&gt; _HomePageState();
}

class _HomePageState extends State&lt;HomePage&gt; {
  late Query _query;
  final Map&lt;String, dynamic&gt; _filters = {
    &#39;price&#39;: 500,
    &#39;meter&#39;: 120,
  };
@override
  void initState() {
    super.initState();
    _query = FirebaseFirestore.instance.collection(&#39;items&#39;);
    for (var key in _filters.keys) {
      if (_filters[key] != null) {
        _query = _query.where(key, isGreaterThanOrEqualTo: _filters[key]);
      }
    }
  }
@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(&#39;My App&#39;),
      ),
      body: StreamBuilder&lt;QuerySnapshot&gt;(
        stream: _query.snapshots(),
        builder: (BuildContext context, AsyncSnapshot&lt;QuerySnapshot&gt; snapshot) {
          if (!snapshot.hasData) {
            return const CircularProgressIndicator();
          }
          List&lt;DocumentSnapshot&gt; documents = snapshot.data!.docs;
          return ListView.builder(
            itemCount: documents.length,
            itemBuilder: (BuildContext context, int index) {
              DocumentSnapshot document = documents[index];
              return ListTile(
                title: Text(&#39;${document[&#39;price&#39;]}&#39;),
                subtitle: Text(
                    &#39;${document[&#39;meter&#39;]} m&#178; / ${document[&#39;landMeter&#39;]} m&#178;&#39;),
              );
            },
          );
        },
      ),
    );
  }
}

is there any way to work around this limitation?
or dynamic querying?

答案1

得分: 1

在Firestore文档的查询限制部分提到:

在复合查询中,范围(<、<=、>、>=)和不等于(!=、not-in)比较必须全部过滤相同的字段。

您的代码在pricemeter字段上都添加了isGreaterThanOrEqualTo(>=)条件,这不符合这个限制。

问题不在于您正在动态构建查询,而是您尝试在多个字段上添加isGreaterThanOrEqualTo条件,而Firestore不支持这样做。


一个选项是在数据库中只执行一个条件,并在应用代码中进行进一步的过滤。


另一个解决方法是(通常在处理NoSQL数据库时如此)添加附加数据以允许使用这种用例,尽管我不确定是否适用于这里。

我能想到的最接近的方法是,您可以添加一个包含这两个值的单个字段:

price_meter: "500_120"

然后,您可以对这个组合值进行notEqual查询,但要实现双重>=可能不容易,所以客户端过滤可能是您唯一的选择。

英文:

If you check the Firestore documentation on query limitations it says:

> In a compound query, range (<, <=, >, >=) and not equals (!=, not-in) comparisons must all filter on the same field.

Your code is adding isGreaterThanOrEqualTo (&gt;=) conditions on both price and meter fields, which does not meet this limit.

The problem is not so much that you're building your query dynamically, but that you're trying to add isGreaterThanOrEqualTo conditions on multiple fields, which Firestore doesn't support.


One options is to perform only one condition on the database, and do further filtering in your application code.


Another workaround is (as usual when dealing with NoSQL databases) to add additional data to allow the use-case, although I'm not sure if it applies here.

The closest I can think of, you could add a single field with both of the values:

price_meter: &quot;500_120&quot;

You could then do a notEqual query on this composite value, but it won't be easy to implement a double &gt;= this way, so client-side filtering might be your only option for that.

huangapple
  • 本文由 发表于 2023年3月7日 18:12:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75660589.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定