简体   繁体   English

Android 房间:针对字符串列查询列表项

[英]Android room: query list items against string column

I have an list of strings:我有一个字符串列表:

val mylist = listOf("cat","flower")

and a table that has a string typed column named question I can write the query to find questions that are exactly matched with one of list items:和一个包含名为question的字符串类型列的表 我可以编写查询来查找与列表项之一完全匹配的问题:

@Query("SELECT * FROM objects WHERE question IN (:mylist)")
List<Object> queryObjects(List<String> mylist);

But in fact the question column data is not of single word type, but string.但实际上问题列数据不是单词类型,而是字符串。 I need to find results that every one of the list items are in that strings.for example the record: is this a cat我需要找到每个列表项都在该字符串中的结果。例如记录: is this a cat

The use of IN is basically an = test of the expression on the the left of the IN clause against the list of values on the right. IN 的使用基本上是对 IN 子句左侧的表达式与右侧值列表的 = 测试。 That is only exact matches are considered.那只是考虑完全匹配。

However, what you want is multiple LIKE 's with wild characters, and an OR between each LIKE eg question LIKE '%cat%' OR question LIKE '%flower%' or perhaps CASE WHEN THEN ELSE END or perhaps a recursive common table expression (CTE).但是,您想要的是多个带有通配符的LIKE ,以及每个LIKE例如问题 LIKE '%cat%' OR question LIKE '%cat%' OR question LIKE '%flower%'CASE WHEN THEN ELSE END或递归公用表表达式之间的 OR (CTE)。

The former two (LIKEs or CASEs) would probably have to be done via an @RawQuery where the LIKE/CASE clauses are built at run time.前两个(LIKE 或 CASE)可能必须通过@RawQuery完成,其中 LIKE/CASE 子句是在运行时构建的。

The Recursive CTE option would basically build a list of words (but could get further complicated if, anything other than spaces, such as punctuation marks were included.)递归 CTE 选项基本上会构建一个单词列表(但如果包含除空格以外的任何内容(例如标点符号),可能会变得更加复杂。)

Another option could be to consider Full Text Search (FTS).另一种选择是考虑全文搜索 (FTS)。 You may wish to refer to https://www.raywenderlich.com/14292824-full-text-search-in-room-tutorial-getting-started不妨参考https://www.raywenderlich.com/14292824-full-text-search-in-room-tutorial-getting-started

Working Example LIKE's工作示例LIKE's

Here's an example of implementing the simplest, multiple LIKEs clauses separated with ORs:-下面是实现最简单的多个 LIKE 子句的示例,这些子句用 OR 分隔:-

Objects (the Entity):-对象(实体):-

@Entity
data class Objects(
    @PrimaryKey
    val id: Long? = null,
    val question: String
) 

AllDAO (the Daos):- AllDAO (道):-

@Dao
interface AllDAO {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insert(objects: Objects)

    @RawQuery
    fun getObjectsRawQuery(query: SupportSQLiteQuery): List<Objects>

    fun getObjects(values: List<String>): List<Objects> {
        var i = 0
        val sb = StringBuilder().append("SELECT * FROM objects WHERE ")
        for(v in values) {
            if (i++ > 0) {
                sb.append(" OR ")
            }
            sb.append(" question LIKE '%${v}%'")
        }
        sb.append(";")
        return getObjectsRawQuery(SimpleSQLiteQuery(sb.toString()))
    }
}

TheDatabase (not uses .allowMainThreadQueries for convenience and brevity):- TheDatabase (为了方便和简洁,不使用.allowMainThreadQueries ):-

@Database(entities = [Objects::class], version = 1, exportSchema = false)
abstract class TheDatabase: RoomDatabase() {
    abstract fun getAllDAO(): AllDAO

    companion object {
        var instance: TheDatabase? = null
        fun getInstance(context: Context): TheDatabase {
            if (instance == null) {
                instance = Room.databaseBuilder(context,TheDatabase::class.java,"the_database.db")
                    .allowMainThreadQueries()
                    .build()
            }
            return instance as TheDatabase
        }
    }
}

Putting it all together , loading some test data and running some extracts:-把它们放在一起,加载一些测试数据并运行一些提取物:-

class MainActivity : AppCompatActivity() {
    lateinit var db: TheDatabase
    lateinit var dao: AllDAO
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        db = TheDatabase.getInstance(this)
        dao = db.getAllDAO()

        dao.insert(Objects(question = "This is a cat."))
        dao.insert(Objects(question = "This is a flower."))
        dao.insert(Objects(question = "this is nothing."))
        dao.insert(Objects(question = "The quick brown fox jumped over the lazy dog"))

        logObjects(dao.getObjects(listOf("cat","dog")),"Extract1\t")
        logObjects(dao.getObjects(listOf("flower","cat")),"Extract2\t")
        logObjects(dao.getObjects(listOf("brown","nothing")),"Extract3\t")
    }

    fun logObjects(objects: List<Objects>,prefix: String) {
        for (o in objects) {
            Log.d("OBJECTINFO","$prefix Question is ${o.question} ID is ${o.id}")
        }
    }
}

Result结果

2022-04-18 04:58:05.471 D/OBJECTINFO: Extract1   Question is This is a cat. ID is 1
2022-04-18 04:58:05.471 D/OBJECTINFO: Extract1   Question is The quick brown fox jumped over the lazy dog ID is 4

2022-04-18 04:58:05.473 D/OBJECTINFO: Extract2   Question is This is a cat. ID is 1
2022-04-18 04:58:05.473 D/OBJECTINFO: Extract2   Question is This is a flower. ID is 2

2022-04-18 04:58:05.474 D/OBJECTINFO: Extract3   Question is this is nothing. ID is 3
2022-04-18 04:58:05.474 D/OBJECTINFO: Extract3   Question is The quick brown fox jumped over the lazy dog ID is 4
  • Note in the above no consideration has been given to handling an empty list (a failure would occur due to the syntax error of SELECT * FROM objects WHERE; ).请注意,上面没有考虑处理空列表(由于SELECT * FROM objects WHERE;的语法错误,会发生失败)。 That is the example is just intended to demonstrate the basic principle.也就是说这个例子只是为了演示基本原理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM