我在这里遇到了一个小问题,即查询一个字符串以在DB中搜索自动完成功能,我遇到的问题是我需要第一个结果是所有以“开始”开头的语句,然后是包含该语句的语句字符串!
例如:如果我在数据库的表中获得了以下记录:
- 很棒的服务
- 这里还有其他东西
- 额外服务
- 我的服务很棒
- 提供的服务
- 动物园服务
然后我开始输入“服务”,我需要先显示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;
}
}
答案 0 :(得分:1)
我认为问题在于order by name like 'Service%' desc;
部分。
您可以只使用findNative(sql)
最近对Ebean进行了更改,允许在order by子句中使用任意函数,因此您可以尝试更新Ebean版本并执行以下操作:
.orderBy(“类似于“服务%”的名称” desc”)。findList();
答案 1 :(得分:0)
Mothafar。
这是一个好问题。我猜您不喜欢您的解决方案,因为它两次查询数据库。那么先查询然后再排序:
final List<Service> list = Service.find.query().where()
.icontains("name", search)
.findList()
.sort(Comparator.comparingInt(service -> service.getName().indexOf(search)))
);
return list;
这种方式首先出现#5,然后其余的按搜索词的出现索引排序。需要注意的是,排序不是通过数据库完成的。但是也许可以将这种条件整合到orderBy子句中。
欢呼
詹斯