繁体   English   中英

日期范围内按集合计数的休眠搜索顺序

[英]Hibernate Search Order by Collection Count within Date Range

我有两个对象-一个Document对象和一个Hit对象:

Document
    id
    description
    hits (Collection of type Hits)
    ...

Hit
    documentId (Type Document)
    date
    ...

我正在尝试创建一个Hibernate Search查询,该查询搜索文档描述,然后根据给定日期范围内的命中次数对结果进行排序。

我在解决此问题时遇到了一些麻烦。 我已经采取一看这个 ,但考虑到点击的总数,并且不允许动态日期范围查询,桥接字段更新日期无关的。

我目前对我的Document对象有一个索引,可以在description正常工作。 我在想可能需要为Hit对象创建一个索引,针对它的日期范围(按documentId分组)运行一个查询,然后使用针对Document索引的搜索词运行第二个查询。

有了这种策略,我仍然不确定如何:

  1. documentId对点击进行分组
  2. 维持点击查询中结果的顺序
  3. 处理分页。

我的猜测是,我需要从Hits索引中获取所有结果(是否使用某种类型的构面逻辑进行分组/排序?),然后匹配documentId / term并在第二个查询中处理分页。 我只是不确定在使用QueryBuilder接口构建查询时,或者在没有想到的完全不同方法的情况下,这一切会如何。

更新

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
}                                                                                                                              

我可能会使用@IndexedEmbedded将命中索引为文档索引的@IndexedEmbedded 然后,对description字段运行查询,提供自定义的Sort实现。 自定义排序将需要数据范围作为参数,然后计算该日期范围内的匹配数并相应地排序。

最后,我进行了类似于@gmansoor建议的操作-第一个查询术语,返回ID,然后第二次基于这些ID查询。 似乎没有办法在Hibernate Search的单个查询中执行此操作,因此,这似乎是目前最好的解决方案。 如果有人知道更好的方法,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM