Несогласованное индексирование при наличии связи manytomany через объединенную таблицу в поиске в спящем режиме

У меня проблема с индексированием lucene через поиск в спящем режиме:

Домен продукта:

    @Entity
    @Table(name="T_PRD")
    @Indexed
    public class Product implements java.io.Serializable {
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "T_TMPL_ATTR_VALUE", joinColumns = { @JoinColumn(name = "EntityId", unique=false) }, inverseJoinColumns = { @JoinColumn(name = "AttrId", unique=false) }, uniqueConstraints=@UniqueConstraint(columnNames={"EntityId","AttrId"}))
    @IndexedEmbedded(prefix="prd.ca.")
    private Set<TemplateAttribute> customTemplateAttributes;
}

Домен TemplateAttribute:

@Entity
@Table(name = "T_TMPL_ATTRS")
public class TemplateAttribute implements java.io.Serializable {

    @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, mappedBy = "templateAttribute")
    @IndexedEmbedded
    private Set<TemplateAttributeValue> templateAttrValues = new HashSet<TemplateAttributeValue>(0);

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "T_TMPL_ATTR_VALUE", joinColumns = { @JoinColumn(name = "AttrId", unique=false) }, inverseJoinColumns = { @JoinColumn(name = "EntityId", unique=false)}, uniqueConstraints=@UniqueConstraint(columnNames={"EntityId","AttrId"}))


    @ContainedIn
    private Set<Product> product;

@Column(name = "DefaultValue")
private String defaultValue;

}

Домен TemplateAttributeValue (Таблица мостов, в которой есть поле attrValue, содержащее значение для конкретного продукта):

@Entity
@Table(name = "T_TMPL_ATTR_VALUE")
public class TemplateAttributeValue implements java.io.Serializable {

    @DocumentId(name="id")
    @EmbeddedId
    @AttributeOverrides( {
    @AttributeOverride(name = "entityId", column = @Column(name = "EntityId", nullable = false)),
    @AttributeOverride(name = "attrId", column = @Column(name = "AttrId", nullable = false)) })
    @FieldBridge(impl = TemplateAttributeCompositeKeyBridge.class)
    public TemplateAttributeValueId getId() {
        return this.id;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "AttrId", nullable = false, insertable = false, updatable = false)
    @ContainedIn
    public TemplateAttribute getTemplateAttribute() {
        return this.templateAttribute;
    }

    @Column(name = "AttrValue")
    @Field(index = Index.YES, analyze = Analyze.YES, norms = Norms.NO, store = Store.NO)
    public String getAttrValue() {
        return this.attrValue==null?"":this.attrValue;
    }
}

Я вызвал методы doIndex, как показано ниже:

private void doIndex() throws InterruptedException {
    Session session = getSessionFactory().openSession();
    session.enableFilter("onlyProductTemplate");
    FullTextSession fullTextSession = Search.getFullTextSession(session);
    fullTextSession.createIndexer().startAndWait();

    fullTextSession.close();
}

Итак, давайте предположим, например, данные ниже:

Product:

ID | Name
----------
 1 | Prd1
 2 | Prd2
 3 | Prd3

Template Attribute:

AttrId | DefaultValue
---------------------
1 | Template1
2 | Template2


Template Attribute Value:

AttrId | EntityId | AttrValue
-----------------------------
1 | 1 | Template1
2 | 1 | Template2_modified
1 | 2 | Template1Updated
1 | 2 | Template2
1 | 3 | Template1
2 | 3 | Template2_newValue

Поэтому, когда я создаю индекс для сущности продукта, каждый продукт генерирует индекс все AttrValue, определенный в значении атрибута шаблона.

Из-за этого, когда поиск по конкретному продукту имеет какое-то соответствие любому значению атрибута шаблона, он возвращает все продукты в списке.

Итак, как решить эту проблему при поиске в спящем режиме.


person Atul Kumar    schedule 26.06.2014    source источник


Ответы (1)


Я получил решение, реализовав StringBridge, как показано ниже:

    @Override
    public String objectToString(Object value) {
        if(value != null) {
            String templateType = null;  
            if(value instanceof Set) {
                StringBuilder strBuild = new StringBuilder();
                Set<TemplateAttribute> setOfTempAttr = (Set<TemplateAttribute>) value;
                for(TemplateAttribute tempValue : setOfTempAttr) {
                    int productID = tempValue.getProduct().getProductId();
                    Set<TemplateAttributeValue> setOfTempAttrValues = tempValue.getTemplateAttrValues();

                    for (TemplateAttributeValue taValue : setOfTempAttrValues) {
                        int entityID = taValue.getId().getEntityId();
                        if(entityID == productID) {
                            strBuild.append(" " + taValue.getAttrValue());
                        }

                    }
                }
                return strBuild.toString();
            } else if(value instanceof String) {
                templateType = (String) value;
            }
            return templateType;
        }
        return null;
}

Это означает, что нам нужно игнорировать эти attrValue (s), которые нужно проиндексировать для продукта, которому они не принадлежат. еще одно изменение удаляет аннотацию @ indexedEmbedded / @ ContainIn и определяет, как показано ниже:

    @Field(index = Index.YES, analyze = Analyze.YES, norms = Norms.NO, store = Store.NO)
    @FieldBridge(impl = TemplateAttributeValueProductFieldBridge.class)
 private Set<TemplateAttribute> customTemplateAttributes;
person Atul Kumar    schedule 28.06.2014