问题描述
以我的Dao中的以下查询为例,我已经能够在Android Room + FTS中实现基本的搜索功能:
@Query("SELECT * FROM Conversation JOIN ConversationFts ON Conversation.id == ConversationFts.id WHERE ConversationFts.title LIKE :text GROUP BY Conversation.id")
public abstract DataSource.Factory<Integer,Conversation> search(String text);
text
在百分号之间传递,例如%lorem%
。
此示例非常适合单个单词的搜索,我想扩展它以能够搜索一个或多个单词,但条件是它们不必按输入顺序排列,但必须匹配所有单词。这意味着这必须是AND
而不是OR
的情况。
我找到了一些SQL查询的示例,但是它们需要针对每种情况量身定制的特定查询,例如:LIKE文本AND LIKE另一个AND LIKE, etc ...解决方案。
如何实现?为了明确起见,我不是要寻找原始查询解决方案,而是要尽可能地坚持使用Room,否则,我宁愿直接使用它而不是求助于原始查询。
编辑:每个请求均添加示例
我搜索do
,返回的结果包括标题中包含do
的所有匹配项,即使是部分匹配项
我搜索do
和test
,返回的结果包括所有包含do
和test
的匹配项,但是没有特定的顺序,即使它们是部分匹配项也是如此。
但是,如果在文本中仅找到其中之一,则不会在结果中返回它。例如,如果找到do
,但没有找到test
,那么它将不属于结果的一部分。
解决方法
我认为除了动态创建原始查询外,没有其他方法可以做到这一点。您可以编写其他方法,如下所示:
public abstract class ConversationDao {
public DataSource.Factory<Integer,Conversation> search(String text) {
StringBuilder builder = new StringBuilder();
String[] words = text.split("\\s+");
if (words.length > 0) {
builder.append(" WHERE ");
}
for (int i = 0; i < words.length; i++) {
builder.append("ConversationFts.title LIKE %").append(words[i]).append("%");
if (i < words.length - 1) {
builder.append(" AND ");
}
}
SupportSQLiteQuery query = new SimpleSQLiteQuery(
"SELECT * FROM Conversation JOIN ConversationFts ON Conversation.id == ConversationFts.id"
+ builder.toString()
+ " GROUP BY Conversation.id"
);
return search(query);
}
@RawQuery
public abstract DataSource.Factory<Integer,Conversation> search(SupportSQLiteQuery query);
}