【问题标题】:Spring JPA find entity where property containing ListSpring JPA 查找包含 List 的属性的实体
【发布时间】:2022-02-03 22:40:24
【问题描述】:

例如:

这是我要搜索的对象的名称属性:

Lorem ipsum dolor sit amet, consectetur adipiscing elit

当我填写 "lo adip tetur" (lo (= Lorem), dipi (=adipiscing), tetur (=consectetur) ) 时,我希望能够找到这个对象。

我尝试在空间上拆分我的 name 属性并将其传递给 jpa 方法,但没有得到任何结果。

List<Obj> findAllByNameIgnoreCaseContaining(String[] splittedName);

解决这个问题的正确方法是什么?谢谢!

【问题讨论】:

  • 我担心来自@Ajay Kumar 的链接答案在文本片段搜索方面可能会不足,因为例如“in”和“like”不能组合
  • 你说得对,这对我的用例来说确实是个问题。感谢您的建议 AjayKumar

标签: spring spring-boot jpa spring-data-jpa


【解决方案1】:

正则表达式查询将允许您指定这种类型的复杂文本搜索条件。
许多数据库都支持正则表达式,并且可以在使用本机查询时提供。

postgres 的示例可能如下所示:

@Query(nativeQuery = true, value =
  "SELECT * FROM my_entity
   WHERE text_column ~ :contentRegex")
List<MyEntity> findByContentRegex(@Param("contentRegex") String contentRegex);

要匹配前三个单词的前两个字符,您可以传递一个像这样的正则表达式:

var result = repository.findByContentRegex("^Lo\S*\sip\S*\sdo.*");

(以Lo开头的字符串,后跟任意数量的非空白字符、空白字符ip、任意数量的非空白字符、空白字符do和一个任意数量的任意字符)

当然,您可以动态组装正则表达式,例如通过连接用户提供的搜索词片段:

List<String> searchTerms = List.of("Lo", "ip", "do"); // e.g. from http request url params
String regex = "^"+String.join("\S*\s", searchTerms) + ".*";
var result = repository.findByContentRegex(regex);

参见例如https://regex101.com/ 用于互动游乐场。


请注意,复杂的表达式可能会导致查询变得昂贵,因此人们可能会在某些时候考虑更高级的方法,例如全文搜索,可以利用特殊的索引。 https://www.postgresql.org/docs/current/textsearch-intro.html
另请注意,setting a query timeout is recommended 用于潜在的敌对参数源。
除此之外,还有更专业的搜索服务器,例如喜欢apache-solr

【讨论】:

  • 感谢您的建议!我的正则表达式看起来像这样,它似乎正在工作: for (String term : searchTerms) { regex.append(String.format("(?=.*%s.*)", escapeSpecialRegexChars(term))); }
猜你喜欢
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
  • 2016-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多