2017-06-16 2 views
0

je cartographie qui ressemble à:recherche Hibernate @IndexEmbedded combine collection dans un domaine

@Entity 
@Table(name = "t_documents") 
@Indexed(interceptor = DocumentIndexingInterceptor.class) 
public class Document implements Serializable { 
    @Id 
    @GeneratedValue 
    @DocumentId 
    private Long id; 

    @IndexedEmbedded(prefix = "sections.", indexNullAs = "null", 
     includePaths = {"body"}) 
    private List<Section> sections; 

//... 
} 

@Entity 
@Table(name = "t_sections") 
@Indexed 
public class Section implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @DocumentId 
    private Long id; 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "ndocumentid") 
    private Document document; 

    @Field(name = "body", 
      analyze = Analyze.YES, 
      index = Index.YES, 
      store = Store.NO, 
      norms = Norms.NO) 
    @Column(name = "vbody") 
    private String body; 

//... 
} 

Maintenant, si j'ai un document d'entité avec deux entités Section ressemblant à:
Section 1 corps: « Répondre à votre question";
Section 2 corps: "Postez votre question";
* Les autres valeurs ne sont pas importantes.

Quand je regarde l'entité indexée du document dans Luc sections.body ressemble:

answer your own question post your question 

Lorsque ce document je recherche les documents contenant phrase « poste de réponse », il trouverait. Ce qui n'est pas mon résultat souhaité. Je veux que ce document soit trouvé seulement si ma chaîne recherchée a trouvé dans le corps simple.

Est-ce encore possible? Sinon, y a-t-il un moyen de réaliser ce que je veux?

Répondre

0

Il s'agit d'une limitation intrinsèque de @IndexedEmbedded sur une collection: tous les éléments des collections sont fusionnés.

La première question à se poser est la suivante: recherchez-vous vraiment des documents? Si vous ne voulez pas que deux mots correspondent à des sections différentes, il est probable que vous souhaitiez rechercher des sections à la place. Si c'est le cas, vous pouvez simplement changer votre requête pour cibler Section.class au lieu de Document.class.


Si vous devez être en mesure de rechercher des champs dans Document aussi, vous pouvez faire intégrer l'inverse: mettre un @IndexedEmbedded sur Section.document, comme ceci:

@Entity 
@Table(name = "t_documents") 
@Indexed(interceptor = DocumentIndexingInterceptor.class) 
public class Document implements Serializable { 
    @Id 
    @GeneratedValue 
    @DocumentId 
    private Long id; 

    @ContainedIn // IMPORTANT: this will ensure that the "section" index is updated whenever a section is updated 
    private List<Section> sections; 

//... 
} 

@Entity 
@Table(name = "t_sections") 
@Indexed // TODO: if you need it, put an interceptor here, just as in Document? 
public class Section implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @DocumentId 
    private Long id; 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "ndocumentid") 
    @IndexedEmbedded(indexNullAs = "null", includePaths = { /* LIST YOUR PATHS HERE */ }) 
    private Document document; 

    @Field(name = "body", 
      analyze = Analyze.YES, 
      index = Index.YES, 
      store = Store.NO, 
      norms = Norms.NO) 
    @Column(name = "vbody") 
    private String body; 

//... 
} 
+0

document est mon entité principale. Il contient BEAUCOUP de champs comme le titre, le statut, l'auteur, les dates, etc. Tous sont indexés et recherchés. par conséquent je veux obtenir une requête comme 'obtenir des documents où le titre égal à" un titre "et l'une des sections contient le mot" quelques mots "' –

+0

@JohnSmith Ok. Si vous n'avez pas envie de lister explicitement les chemins inclus, vous pouvez simplement les omettre: tous les champs seront inclus. Ensuite, la requête que vous avez donnée traduirait comme 'document.title:" un titre "body:" quelques mots "' si vous avez interrogé l'index de la section au lieu de l'index du document. –