我有两个对象 - 一个Document
对象和Hit
对象:Hibernate Search的排序采集日期范围内的数
Document
id
description
hits (Collection of type Hits)
...
Hit
documentId (Type Document)
date
...
我试图创建一个Hibernate搜索查询,以搜索文档描述,然后按给定日期范围内的点击次数对结果进行排序。
我有一点麻烦缠绕我的头围绕如何做到这一点。我查看了this,但它考虑了点击总数,并且不允许动态日期范围查询,因为桥接字段是独立于日期更新的。
目前,我有我的Document
对象的索引与description
工作正常搜索。我想我可能需要创建一个指数为Hit
对象,通过documentId
对其运行查询的日期范围,组,然后运行使用抗Document
索引搜索项的第二个查询。
鉴于这种策略,我仍然不知道如何:
- 组由
documentId
- 命中保持结果的顺序从匹配查询
- 手柄分页。
我的猜测是,我需要得到来自Hits
指数所有结果(使用某种类型的刻面逻辑的分组/排序,也许?),再搭配上documentId
/学期,并在第二个查询处理分页。我只是不确定在使用QueryBuilder接口来构建查询时,所有这些都看起来如何,或者如果有一种完全不同的方式来处理这个问题,我还没有想到。
UPDATE
public class DateRangeDownloadsFieldComparator extends FieldComparator<Integer> {
class DownloadsParser implements FieldCache.IntParser {
@Override
public int parseInt(String string) {
/*
* What do I pass here and what do I do with it?
* Ideally, I would pass the downloads collection and return the size of the
* collection where the download appears within the provided date range, but
* passing a collection here does nothing, as it's silently ignored.
*/
return 0;
}
}
private Calendar startDate;
private Calendar endDate;
private final int[] fieldValues;
private int bottom;
private int[] currentReaderValues;
public DateRangeDownloadsFieldComparator(int numHits, Calendar startDate, Calendar endDate) {
super();
this.startDate = startDate;
this.endDate = endDate;
fieldValues = new int[numHits];
}
@Override
public int compare(int slot1, int slot2) {
return compareValues(fieldValues[slot1], fieldValues[slot2]);
}
@Override
public int compareBottom(int doc) throws IOException {
int currentDoc = currentReaderValues[doc];
return compareValues(bottom, currentDoc);
}
@Override
public int compareValues(Integer v1, Integer v2) {
if (v1 > v2) {
return 1;
}
else if (v1 < v2) {
return -1;
}
else {
return 0;
}
}
@Override
public void copy(int slot, int doc) throws IOException {
int v1 = currentReaderValues[doc];
fieldValues[slot] = v1;
}
@Override
public void setBottom(int slot) {
bottom = fieldValues[slot];
}
@Override
public void setNextReader(IndexReader reader, int docBase) throws IOException {
currentReaderValues = FieldCache.DEFAULT
.getInts(reader, "downloads", new DownloadsParser());
}
@Override
public Integer value(int slot) {
return fieldValues[slot];
}
}
更新2
文档实体
@Entity
@Table(name = "documents")
@Indexed(index = "documents")
public class EDocument {
public static final String FIELD_NAME = "name";
public static final String FIELD_CREATED = "created";
public static final String FIELD_DESCRIPTION = "description";
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created")
@Field(name = FIELD_CREATED)
private Calendar created;
@Column(name = "name")
@Field(name = FIELD_NAME)
private String name;
@Column(name = "description")
@Field(name = FIELD_DESCRIPTION)
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@IndexedEmbedded(depth = 1)
private EUser user;
@OneToMany(
fetch = FetchType.LAZY,
targetEntity = EDownload.class,
mappedBy = "document",
orphanRemoval = true,
cascade = CascadeType.ALL)
@IndexedEmbedded(depth = 1)
private Set<EDownload> downloads;
public EDocument() {
created = Calendar.getInstance();
}
// getters and setters
}
下载实体
@Entity
@Table(name = "downloads")
public class EDownload {
public static final String FIELD_REQUESTED = "requested";
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@Column(name = "requested")
@Field(name = FIELD_REQUESTED)
private Calendar requested;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "document_id", nullable = false)
private EDocument document;
public EDownload() {
requested = Calendar.getInstance();
}
// getters and setters
}
除非您对Hit的搜索可以更改文档的返回数量,否则我会在hibernate中使用第二个查询来按命中次数获得排序。因此,您搜索描述并获取文档ID列表(投影),然后执行第二个查询(native或hql)传递文档ID? Lucene/Hibernate搜索适用于文本的布尔搜索,但不适合您的第二个特定场景。 – gmansoor 2014-12-05 05:16:13