Hibernate Search - 自定义Bridge值不更新

时间:2013-09-17 10:21:19

标签: hibernate lucene hibernate-search

来自:Hibernate Search Order by child-count 我有:

@Indexed
@Entity
public class TParent  implements java.io.Serializable {

.....
private Set<TChild> TChildSet = new HashSet<TChild>(0);

@ContainedIn
@FieldBridge(impl = CollectionCountBridge.class)
@Field(analyze = Analyze.NO)
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="TParent")
public Set<TChild> getTChildSet() {
   return this.TChildSet;
}

@Indexed
@Entity
public class TChild  implements java.io.Serializable {

.....
private TParent TParent;

@IndexedEmbedded
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="parent_id", nullable=false)
public TParent getTParent() {
    return this.TParent;
}

感谢Don Roby,我已经应用了这个CustomBridge

public class CollectionCountBridge extends IntegerBridge {

   @Override
   public String objectToString(Object object) {
     if (object == null || (!(object instanceof Collection))) {
         return null;
     }
     Collection<?> coll = (Collection<?>) object;
     int size = coll.size();
     System.out.println("col.size(): " + size);
     return super.objectToString(size);
  }

}

我正在列出TParents。我正试图通过TChildSet计数来命令它们。 当我首先构建索引时,它完美地工作。我可以列出TParent's并按照TChild的数量对它们进行排序。

FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(luceneQuery, TParent.class);
fullTextQuery.setSort(new Sort(new SortField("TChildSet", SortField.INT, true)));

现在...

当我添加新的TChild时,会执行CustomBridge代码。当我添加TChild时,我希望看到订单更改。

我可以看到TChild计数增加了(根据CustomBridge代码中的System.out.println())。

但是,查询没有正确排序。从最初构建索引时开始的原始排序顺序仍然存在。添加新的TChild对排序顺序没有影响。 我想索引没有更新,但我不确定。

任何帮助或指示都会很棒。

非常感谢

约翰

修改 当前的问题是该值未在索引中更新。这可以通过Luke看到。

2 个答案:

答案 0 :(得分:2)

我认为你的问题是你将数字(整数)索引为字符串,但你想要数字排序。

您有两种选择。如果你继续使用字符串方法,你将需要创建填充字符串(例如,如果你知道你从来没有超过100个元素,你将填充所有数字,如003等)。这样,词汇排序将表现为数字排序。

可能更好的选择是将计数索引为数字字段。这样排序将自动数字化。像(未经测试)的东西:

public class CollectionCountFieldBridge {

   void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
     if (object == null || (!(object instanceof Collection))) {
         return null;
     }
     Collection<?> coll = (Collection<?>) object;
     int size = coll.size();
     luceneOptions.addNumericFieldToDocument( name, value, document );;
   }
}

答案 1 :(得分:1)

问题

在实体中,对不是数据库表字段的索引字段执行更新,然后保存实体将不会导致索引更新。 (将实体保存为对数据库表字段的索引字段的更新将导致自动更新索引。)

<强>解决方案

(简单)手动更新索引

public static void addTChild() {
    Session session = null;
    try {
        session = HibernateUtil.getSession();
        session.beginTransaction();
        TParent tParent = (TParent)session.get(TParent.class, 6L);
        TChild tChild = new TChild(tParent, "Auto added " + new Date().toString(), 'y');
        Long id  = (Long)session.save(tChild);
        tChild = (TChild)session.get(TChild.class, id);
        tParent.getTChildSet().add(tChild);
        session.save(tParent);

        /*
         * Manually update the index.
         * Necessary due to fact that the index field updated
         * is not a DB table field and hence will not cause an index update
         */
        FullTextSession fullTextSession = Search.getFullTextSession(session);
        fullTextSession.index(tParent);

        session.getTransaction().commit();
    } catch (Exception ex) {
        session.getTransaction().rollback();
        ex.printStackTrace();
    } finally{
        if(session != null) {
            session.close();
        }
    }
}

实体:

/*
 * TParent
 */
@ContainedIn
@FieldBridge(impl = CollectionCountBridge.class)
@Field(analyze = Analyze.NO, store = Store.YES, name = "cCount")
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="TParent")
public List<TChild> getTChildSet() {
    return this.TChildSet;
}

/*
 * TChild
 */
 @IndexedEmbedded
 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name="parent_id", nullable=false)
 public TParent getTParent() {
    return this.TParent;
 }

就我而言,就是这样。