我在包含 BEGINSWITH (或 CONTAINS )的查询中遇到问题。我正在尝试遵循 Mongo Db 文档中的示例:
用于查找
(所有这些都在 viewModel 中)
这是查询:
val searchResults = realm
.query<Pantry>("itemName BEGINSWITH $0", searchText.value)
.find()
.asFlow()
.map { results ->
results.list.toList()
}
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
emptyList()
)
searchText
是一个字符串,其中包含用户输入的搜索模式,用于查找 Pantry 模型的实例。这是通过使用 TextField 完成的。
'realm' 定义如下: private val Realm =
MyApp.realm
.
我的应用程序是:
class MyApp: Application() {
companion object {
lateinit var realm: Realm
}
override fun onCreate() {
super.onCreate()
realm = Realm.open(
configuration = RealmConfiguration.create(
schema = setOf(
Pantry::class,
Department::class,
Market::class,
)
)
)
}
}
我实现了这个函数来看看发生了什么;查询是否执行任何操作:
suspend fun checkSearchResults(){
searchResults.collect { results ->
if (results.isEmpty()) {
Log.d("Search", "No search results found")
} else {
// Loop through or access items in results
for (item in results) {
Log.d("Search", "Found item: ${item.itemName}")
}
}
}
}
这是用户输入字符时的日志:
The value of searchText: h
D Found item: bananas
D Found item: clorox
D Found item: garbanzos
D Found item: ham
D Found item: laundry detergent, pods
D Found item: milk
D Found item: olives
D Found item: pastries
D Found item: salmon
D Found item: water, sparkling
D The value of searchText: ha
D Found item: bananas
D Found item: clorox
D Found item: garbanzos
D Found item: ham
D Found item: laundry detergent, pods
D Found item: milk
D Found item: olives
D Found item: pastries
D Found item: salmon
D Found item: water, sparkling
D The value of searchText: ham
D Found item: bananas
D Found item: clorox
D Found item: garbanzos
D Found item: ham
D Found item: laundry detergent, pods
D Found item: milk
D Found item: olives
D Found item: pastries
D Found item: salmon
D Found item: water, sparkling
这是整个数据库。
因此,从日志中可以明显看出,查询忽略了过滤器并且包含了所有实例。
谁能指出我的失败之处?我想我非常密切地关注文档。
更新: 如果我使用这样的查询:
.query<Pantry>("itemName = $0", searchText.value)
并使用已知的 itemName
,结果是一个空列表。
更新2:
searchResults
不更新。我的理解是,因为它是一个 StateFlow
,所以每次条件发生变化时它都会更新 (searchtext.value
),但它不会发生。
这就是问题所在:
searchResults
的值不是更新,因此即使textField
向searchText variable
发送字符,什么也没有发生。
解决方案:强制更新变量searchResults
。这是通过将
searchResults
的代码封装在函数中并从
onValueChange
中的
textField
调用该函数来完成的。并发症:我的理解是,仅仅因为调用了一个函数,并不一定会在
StateFlow
实体上生成更新,因此通过将其包含在.collect 中可以实现这一点。
viewModel
和
Composable
之间的复杂性以及在
variables
声明中使用 var 和 val。因此,为了解决上述并发症,我声明如下:
private val _searchResults = MutableStateFlow<List<Pantry>>(emptyList())
var searchResults: StateFlow<List<Pantry>> = _searchResults.asStateFlow()
1 用于 viewModel,另一个用于 Composable。这就是函数:
suspend fun fetchSearchResults(searchTerm: String) {
realm.query<Pantry>("itemName CONTAINS $0", searchTerm)
.find()
.asFlow()
.map { results -> results.list.toList() }
.collect { filteredList ->
_searchResults.value = filteredList
}
}
由于“.collect”,它需要位于 suspend function
中。因此该函数是从
textField
:调用的
TextField(
value = searchText,
onValueChange = { viewModel.changeText(it)
scope.launch {
viewModel.fetchSearchResults(it)
}
},
效果非常好。测试了它CONTAINS和BEGINSWITH,两者都有效。