android - firestore 中日期字段的查询不起作用

标签 android firebase kotlin google-cloud-firestore

我是编程新手,只是作为一种爱好,通常如果我遇到问题,我可以在互联网上的某个地方找到答案,但花了两天的时间,仍然无法解决这个问题。我正在使用 kotlin 和 android studio 编写一个 android 应用程序。第一次提问,请轻点!

我在 Firestore 中保存了一个日期,作为通过 hashmap 使用此代码保存的时间戳

    val dateFormat = SimpleDateFormat("dd-MM-yyyy")
    val date = findViewById<TextView>(R.id.textMatchDate).text.toString()
    val timeStamp = Timestamp(dateFormat.parse(date)

timeStamp 然后保存到 firestore。

我的检索代码是

        val date = "01-01-2020"
        val date1 = dateFormat.parse(date)
        val startDate = Timestamp(date1)

val db = FirebaseFirestore.getInstance()
        db.collection("snookerResults")
            .whereGreaterThan("date", startDate)
            .whereEqualTo("homeTeam", team)
            .get()
            .addOnSuccessListener {...}

为了简单起见,我将获取 startDate 的方法放在 0f 中,它是通过编程导出的,但是相同格式的字符串。 尽管知道应该返回结果,但我得到一个空数组。如果我注释掉 whereGreaterThan 行,我会得到返回的所有结果。

我有日志输出来说明问题,当我正常运行时,我得到以下输出:-

2020-08-29 23:27:04.858 17112-17112/com.example.aggregatecalculator I/让分:选择的球队是不伦瑞克队

2020-08-29 23:27:05.086 17112-17112/com.example.aggregatecalculator 我/障碍:开始日期是时间戳(秒=1577836800,纳秒=0)

如果我注释掉 whereGreaterThan 行,那么我会得到此输出

2020-08-29 23:37:08.331 18164-18164/com.example.aggregatecalculator I/盘口:选择的球队是不伦瑞克队

2020-08-29 23:37:08.582 18164-18164/com.example.aggregatecalculator 我/障碍:开始日期是时间戳(秒=1577836800,纳秒=0)

2020-08-29 23:37:08.583 18164-18164/com.example.aggregatecalculator I/handicap: 日期是 [2020 年 1 月 1 日星期三 00:00:00 GMT+00:00 2020 年 9 月 30 日星期三00:00:00 GMT+01:00 2020]

2020-08-29 23:37:08.793 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1583712000,纳秒=0)

2020-08-29 23:37:08.793 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1575244800,纳秒=0)

2020-08-29 23:37:08.793 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1569798000,纳秒=0)

2020-08-29 23:37:08.794 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1572825600,纳秒=0)

2020-08-29 23:37:08.794 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1582502400,纳秒=0)

2020-08-29 23:37:08.794 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1584921600,纳秒=0)

2020-08-29 23:37:08.795 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1568588400,纳秒=0)

2020-08-29 23:37:08.795 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1574035200,纳秒=0)

2020-08-29 23:37:08.795 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1571612400,纳秒=0)

2020-08-29 23:37:08.796 18164-18164/com.example.aggregatecalculator I/handicapresults: 日期是时间戳(秒=1571007600,纳秒=0)

如您所见,时间戳的格式相同,并且 3 个返回的时间戳大于 startdate,因此理论上应使用 whereGreaterThan 子句返回

enter image description here

fun getNewHcap(team: String){
val players = arrayListOf<String>()
val db = FirebaseFirestore.getInstance()
db.collection("SnookerPlayers")
    .whereEqualTo("league", "Big Table Monday")
    .whereEqualTo("team", team)
    .get()
    .addOnSuccessListener { task ->
        for (doclist in task){
            val player = doclist["player"].toString()
            players.add(player)
        }
        val dates = hcapMinMaxDate()
        val dateFormat = SimpleDateFormat("dd-MM-yyyy")
        val date = "01-01-2020"
        val date1 = dateFormat.parse(date)
        val startDate = Timestamp(date1)
        val endDate = Timestamp(dates[1])
        Log.i("handicap", "startdate is $startDate")
       // Log.i("handicap", "startdate is $endDate")

        val db = FirebaseFirestore.getInstance()
        db.collection("snookerResults")
            //.whereGreaterThan("date", startDate)
            .whereEqualTo("homeTeam", team)

           //.whereLessThan("date", endDate)
            .get()
            .addOnSuccessListener { task ->
                for (docList in task){
                   // val player = docList["home player 1"].toString()
                    val date = docList["date"].toString()

                    Log.i("handicapresults", "date is $date")
                }
            }


        Log.i("handicap", "date is $dates")

    }
Log.i("handicap", "chosen team is $team")

最佳答案

I get an empty array despite knowing there are results that should be returned. If I comment out the whereGreaterThan() line I get all results returned.

您得到一个空数组很可能是因为以下代码行:

db.collection("snookerResults")
    .whereGreaterThan("date", startDate)
    .whereEqualTo("homeTeam", team)
    .get()
    .addOnSuccessListener {...}

这是因为在同一查询中调用 .whereGreaterThan() 以及 .whereEqualTo() 需要索引。该索引可以在您的 Firebase Console 中手动创建或者,如果您使用的是 Android Studio,您会在 logcat 中找到一条听起来像这样的消息:

FAILED_PRECONDITION: The query requires an index. You can create it here: ...

您只需单击链接或将 URL 复制并粘贴到网络浏览器中,系统就会自动创建您的索引。等待几分钟,直到索引创建完毕,您将获得所需的结果。

但是,这种方法可能不是最好的方法,因为您需要为数据库中的每个主队创建一个索引。如果您有几个或固定数量的团队,那么它会起作用,但如果您有很多团队,那么就会很困难,建议复制数据。这种做法称为非规范化,对于 Cloud Firestore 来说这是很常见的做法。如果您是NoSQL数据库的新手,为了更好地理解,我建议您观看这个视频,Denormalization is normal with the Firebase Database 。它适用于 Firebase 实时数据库,但相同的原则也适用于 Cloud Firestore。除此之外,我想您可能也对我在以下帖子中的回答感兴趣:

What is denormalization in Firebase Cloud Firestore?

因此,在您的特定情况下,我将创建一个如下所示的新集合:

Firestore-root
  |
  --- homeSnookerResults (collection)
         |
         --- homeTeamId (document)
               |
               --- allResults (collection)
                     |
                     --- resultIdOne (document)
                           |
                           --- //result object properties

在这种情况下,看起来像这样的查询就可以解决问题:

db.collection("homeSnookerResults")
    .document(homeTeamId)
    .collection("allResults")
    .whereGreaterThan("date", startDate)
    .get()
    .addOnSuccessListener {...}

不需要索引的情况。

关于android - firestore 中日期字段的查询不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63650722/

相关文章:

android - 使用 OneSignal 发送通知黑白设备

firebase - location.protocol"必须是 http 或 https

android - 如何在 Jetpack Compose 中对齐底部一行?

java - 在 Android EditText 中,有没有办法强制每个字符为小写?

android - InAPPBilling中IABHelper和IInAppBillingService的区别

android - 如何在使用 Apollo 生成代码时修复 'main GraphQL source' 错误?

java - Android Java改变程序中的主题

android - 向 Snackbar View 添加边距

java - 从 firebase 的导航栏中加载个人资料图像和用户名

android - 如果回收器 View 项中的数据为空,则不显示 View 持有者