【问题标题】:Ebean query for string that startsWith then contains a specific string开始的字符串的 Ebean 查询然后包含特定的字符串
【发布时间】:2018-11-18 10:09:06
【问题描述】:

我在这里遇到了一个小问题,查询一个字符串以在数据库中搜索自动完成功能,我得到的问题是我需要首先结果是所有“开始”的语句,然后是包含该功能的语句字符串!

例如:如果我在数据库的一个表中得到以下记录:

  1. 提供很棒的服务
  2. 这里有别的东西
  3. 额外服务
  4. 我的服务很棒
  5. 提供服务
  6. 动物园服务

我开始输入“服务”,我需要先显示第 5 项,然后是其余项目(1、3、4、6)

我知道如何在 MySQL 中做到这一点,例如:

select * from `services` where `name` like '%Service%' order by `name` like 'Service%' desc;

或者可能像这里提到的方式:MySQL order by "best match"

但我需要在 Ebean 中执行此操作。 我试过了:

return Service.find.query().where().icontains("name", search).findList()

但是这个返回 1, 3, 4, 5, 6,

现在我执行以下操作:

final List<Service> list = Service.find.query().where()
            .istartsWith("name", search)
            .orderBy("name").findList(); // First query 

            list.addAll(Service.find.query().where()
            .icontains("name", search)
            .not().istartsWith("name", search)
            .orderBy("name").findList()); // Then add the results for the second query
return list;

这将完成工作,5、1、3、4、6,但我不喜欢它,因为我用 2 个查询访问数据库,而且我确实在第二个查询中排除了复杂数据类型查询中的第一个查询,但无论如何,这是正确的方法吗?如果没有,您有更好的方法的建议或解决方案吗?

表格:

CREATE TABLE `services` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE services ADD UNIQUE `uq_services_name`(name);

EBean 实体 Service.java:

@Entity
@Table(name = "services")
public class Service extends BaseModel<Service> {
    public static Finder<Integer, Service> find = new Finder<>(Service.class);

    @Column(nullable = false, unique = true)
    private String name;

    // ... setters and getters

}

BaseModel.java:

@MappedSuperclass
public abstract class BaseModel<T> extends Model {

    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    public final Integer getId() {
        return id;
    }

    @SuppressWarnings("unchecked")
    public final T setId(Integer id) {
        this.id = id;
        return (T) this;
    }
}

【问题讨论】:

    标签: java playframework ebean


    【解决方案1】:

    我认为问题出在order by name like 'Service%' desc; 部分。

    • 你可以只使用 findNative(sql)

    • 最近对 Ebean 也进行了更改,以允许 order by 子句中的任意函数,因此您可以尝试更新您的 Ebean 版本并执行以下操作:

      .orderBy("name like 'Service%' desc").findList();

    【讨论】:

      【解决方案2】:

      莫萨法尔。

      这是个好问题。我猜你不喜欢你的解决方案,因为它两次查询数据库。那么先查询再排序呢:

      final List<Service> list = Service.find.query().where()
              .icontains("name", search)
              .findList()
              .sort(Comparator.comparingInt(service -> service.getName().indexOf(search)))
      );
      return list;
      

      这种方式#5 先出现,然后是搜索词的外观索引排序的其余部分。需要注意的是,排序不是通过数据库完成的。但也许可以将这样的条件整合到 orderBy-clause 中。

      干杯

      詹斯

      【讨论】:

      • 谢谢,但问题是处理器一遍又一遍地处理每条记录的搜索真的很痛苦,大约有 20K 条记录,所以听起来像是 2 个查询以更好的结尾性能比这,我想,对吗?
      • 好的。但是,排序将仅应用于结果集。这也会有 20k 条记录吗?
      • 在最坏的情况下,是的,在大多数情况下,更容易达到 10Ks 左右,它是自动完成的,所以你可以想象得到命中的频率。
      • true,所以对于自动完成,也许某种节流是有意义的:AJAX 仅每秒请求一次,而不是在每个字母之后。最少 2 个或 3 个字母的长度,这样的事情会有所帮助。这不应该对用户体验造成太大伤害。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 2011-05-14
      • 2012-03-10
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多