使用 Realm SDK 来自 MongoDB Atlas 的空数据响应

问题描述 投票:0回答:1

我遇到一个问题,即使用 Realm SDK 从 MongoDB Atlas 获取数据时收到空响应。我尝试了各种故障排除步骤,包括删除和重新创建数据库,但问题仍然存在。我在 Android 应用程序中使用 Google One Tap 登录和 JWT 身份验证。此外,我已重新启动领域同步,但我仍然收到一个空对象作为响应。

下面是日记模型,Diary类代表日记条目的模型,并使用Realm SDK的RealmObject作为基类。它包括 _id、ownerId、心情、标题、描述、图像和日期等属性。 -

package com.krish.diaryapp.model

import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.ObjectId
import io.realm.kotlin.types.RealmInstant
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey

open class Diary : RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId.create()
    var ownerId: String = ""
    var mood: String = Mood.Neutral.name
    var title: String = ""
    var description: String = ""
    var images: RealmList<String> = realmListOf()
    var date: RealmInstant = RealmInstant.from(System.currentTimeMillis(), 0)
}

这是用于处理请求状态的 RequestState 密封类:

package com.krish.diaryapp.util

sealed class RequestState<out T> {
    object Idle : RequestState<Nothing>()
    object Loading : RequestState<Nothing>()
    data class Success<T>(val data: T) : RequestState<T>()
    data class Error(val error: Throwable) : RequestState<Nothing>()
}

MongoRepository 接口定义了与 MongoDB 交互的契约。它包括用于设置 Realm 配置的 configureTheRealm() 函数和用于以日记流形式检索日记的 getAllDiaries() 函数。

以下是实现 MongoRepository 接口的 MongoDB 对象的代码:

package com.krish.diaryapp.data.repository

import com.krish.diaryapp.model.Diary
import com.krish.diaryapp.util.RequestState
import kotlinx.coroutines.flow.Flow
import java.time.LocalDate

typealias Diaries = RequestState<Map<LocalDate, List<Diary>>>

interface MongoRepository {
    fun configureTheRealm()
    fun getAllDiaries(): Flow<Diaries>
}

MongoDB 对象负责配置 Realm 并从 MongoDB 检索日记。它使用当前用户在configureTheRealm()函数中初始化Realm配置,并为用户的日记设置初始订阅。 getAllDiaries() 函数从 Realm 检索日记并将结果映射到 Diaries 对象。

package com.krish.diaryapp.data.repository

import android.util.Log
import com.krish.diaryapp.model.Diary
import com.krish.diaryapp.util.Constants.APP_ID
import com.krish.diaryapp.util.RequestState
import com.krish.diaryapp.util.toInstant
import io.realm.kotlin.Realm
import io.realm.kotlin.ext.query
import io.realm.kotlin.log.LogLevel
import io.realm.kotlin.mongodb.App
import io.realm.kotlin.mongodb.sync.SyncConfiguration
import io.realm.kotlin.query.Sort
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import java.time.ZoneId

object MongoDB : MongoRepository {
    private val app = App.create(APP_ID)
    private val user = app.currentUser
    private lateinit var realm: Realm

    init {
        configureTheRealm()
    }

    override fun configureTheRealm() {
        if (user != null) {
            val config = SyncConfiguration.Builder(user, setOf(Diary::class))
                .initialSubscriptions { sub ->
                    add(
                        query = sub.query<Diary>(query = "ownerId == $0", user.identity),
                        name = "User's Diaries"
                    )
                }
                .log(LogLevel.ALL)
                .build()
            realm = Realm.open(config)
        }
    }



    override fun getAllDiaries(): Flow<Diaries> {
        return if (user != null) {
            try {
                realm.query<Diary>(query = "ownerId == $0", user.identity)
                    .sort(property = "date", sortOrder = Sort.DESCENDING)
                    .asFlow()
                    .map { result ->
                        RequestState.Success(
                            data = result.list.groupBy {
                                it.date.toInstant()
                                    .atZone(ZoneId.systemDefault())
                                    .toLocalDate()
                            }
                        )
                    }

            } catch (e: Exception) {
                flow { emit(RequestState.Error(e)) }
            }
        } else {
            flow { emit(RequestState.Error(UserNotAuthenticatedException())) }
        }
    }
}

private class UserNotAuthenticatedException : Exception("User is not Logged in.")

HomeViewModel 负责管理主屏幕的状态和数据。它包括保存日记当前状态的日记属性。 observeAllDiaries() 函数从 MongoDB 收集 getAllDiaries() 流并相应地更新日记状态。

package com.krish.diaryapp.presentation.screens.home

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.krish.diaryapp.data.repository.Diaries
import com.krish.diaryapp.data.repository.MongoDB
import com.krish.diaryapp.util.RequestState
import kotlinx.coroutines.launch

class HomeViewModel : ViewModel() {
    var diaries: MutableState<Diaries> = mutableStateOf(RequestState.Idle)

    init {
        observeAllDiaries()
    }


    private fun observeAllDiaries() {
        viewModelScope.launch {
            MongoDB.getAllDiaries().collect { result ->
                diaries.value = result
            }
        }
    }

}

我在 mongoDb Atlas 中使用以下架构。

{
  "title": "Diary",
  "bsonType": "object",
  "required": [
    "_id",
    "ownerId",
    "mood",
    "title",
    "description",
    "date"
  ],
  "properties": {
    "_id": {
      "bsonType": "objectId"
    },
    "date": {
      "bsonType": "date"
    },
    "images": {
      "bsonType": "array",
      "items": {
        "bsonType": "string"
      }
    },
    "description": {
      "bsonType": "string"
    },
    "mood": {
      "bsonType": "string"
    },
    "ownerId": {
      "bsonType": "string"
    },
    "title": {
      "bsonType": "string"
    }
  }
}

These are the database access rules which I have configured in Atlas

Here is the MongoDb Atlas Log of the query being made.

Here is the Collection

android mongodb kotlin realm android-jetpack-compose
1个回答
0
投票

在 MongoDB 对象中进行这些更改,它应该可以工作。

对于此代码部分:

val config = SyncConfiguration.Builder(user, setOf(Diary::class))
                .initialSubscriptions { sub ->
                    add(
                        query = sub.query<Diary>(query = "ownerId == $0", user.identity),
                        name = "User's Diaries"
                    )
                }

像这样修改第二行:

.initialSubscriptions(rerunOnOpen = true)

© www.soinside.com 2019 - 2024. All rights reserved.