查询Firestore中的日期字段不起作用

时间:2020-08-29 18:57:15

标签: android firebase kotlin google-cloud-firestore

我是编程的新手,只是一个爱好,通常,如果我有问题,我可以在互联网上的某个地方找到答案,但是花了2天的大部分时间,但仍然无法解决这个问题。我正在使用kotlin和android studio编写一个android应用程序。提出第一个问题,请保持温柔!

我有一个保存在Firestore中的日期作为时间戳,并通过哈希映射与此代码一起保存了

    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 {...}

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

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

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 I /障碍:startdate是时间戳(秒= 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 I /障碍:startdate是Timestamp(seconds = 1577836800,nanoseconds = 0)

2020-08-29 23:37:08.583 18164-18164 / com.example.aggregatecalculator I /障碍:日期为[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:日期为Timestamp(seconds = 1583712000,nanoseconds = 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:日期为Timestamp(seconds = 1569798000,nanoseconds = 0)

2020-08-29 23:37:08.794 18164-18164 / com.example.aggregatecalculator I / handicapresults:日期为Timestamp(seconds = 1572825600,nanoseconds = 0)

2020-08-29 23:37:08.794 18164-18164 / com.example.aggregatecalculator I / handicapresults:日期为Timestamp(seconds = 1582502400,nanoseconds = 0)

2020-08-29 23:37:08.794 18164-18164 / com.example.aggregatecalculator I / handicapresults:日期为Timestamp(seconds = 1584921600,nanoseconds = 0)

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

2020-08-29 23:37:08.795 18164-18164 / com.example.aggregatecalculator I / handicapresults:日期为Timestamp(seconds = 1574035200,nanoseconds = 0)

2020-08-29 23:37:08.795 18164-18164 / com.example.aggregatecalculator I / handicapresults:日期为Timestamp(seconds = 1571612400,nanoseconds = 0)

2020-08-29 23:37:08.796 18164-18164 / com.example.aggregatecalculator I / handicapresults:日期为Timestamp(seconds = 1571007600,nanoseconds = 0)

如您所见,时间戳是相同的格式,并且返回的3个时间戳大于startdate,因此在theary中应使用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")

1 个答案:

答案 0 :(得分:2)

尽管知道有应该返回的结果,但是我得到了一个空数组。如果我将whereGreaterThan()行注释掉,则会得到所有结果。

由于以下代码行,您很可能会得到一个空数组:

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

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

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

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

但是,这种方法可能不是最佳方法,因为您需要为数据库中的每个homeTeam创建一个索引。如果您有几个或固定数量的团队,这将起作用,但是如果您有很多团队,这将很困难,建议您重复数据。这种做法称为非规范化,对于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 {...}

在这种情况下,不需要索引。