views:

171

answers:

3

Hi,

Let's say I have following classes. (only most important things included)

public class Client {
    /* Some Properties */
}

public class ClientDocumentAssociation {
    @ManyToOne
    private Client client;

    /* Some Properties */
}

@Indexed
public class Document {
    @OneToOne
    private ClientDocumentAssociation clientAssociation;

    @Field(name = "text")
    private String text;

    /* Some Properties */
} 

My basic document search is like this:

public List<AbstractDocument> searchDocuments(String text) {
    if (text == null) {
        return newArrayList();
    }

    FullTextEntityManager ftem = Search.getFullTextEntityManager(entityManagerProvider.get());
    MultiFieldQueryParser parser = new MultiFieldQueryParser(DOCUMENT_FIELDS, new StandardAnalyzer());
    parser.setDefaultOperator(Operator.AND);
    FullTextQuery ftq;

    try {
        Query q = parser.parse(text + "*");

        ftq = ftem.createFullTextQuery(q, Document.class);

        ftq.setMaxResults(20);

        List<AbstractDocument> results = ftq.getResultList();
        return results;
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return newArrayList();
}

Now, I want to be able to search for documents, but not in the scope of the whole index, but just find documents that belong to given Client. The only thing that comes to my mind is adding the association to the index and add client id to the appropriate field in search. But that does not seem right. There must be another option and that's what I am asking for.

A: 

Ok I actually found a solution. The thing I (and anyone who was searching for solution of the same problem) needed is setting up Criteria for the FullTextQuery.

    Session session = (Session) ftem.getDelegate();
    Criteria criteria = session.createCriteria(Document.class).createCriteria("clientAssociation").add(
            Restrictions.eq("client", owner));

    /* .... */

    ftq.setCriteriaQuery(criteria);

Seems to work ok :)

Piotr Jakubowski
This is not recommended. For example getResultSize() will return an incorrect value and pagination will be screwed.I'd recommend Hardy's or Kango_V's solutions
Emmanuel Bernard
+1  A: 

Why does your initial idea seem to be wrong? In fact indexing all the data needed for your search is the recommended way of doing this. That's what @IndexedEmbedded is there for. Indexing the data will also give you more flexibility for changes in the query and/or new queries.

Hardy
Well I thought that using indexing for some values would not be appropriate (eg filtering on some boolean data doesn't seem right) + given example is simplified and real associations are far more complex -therefore I wanted to filter results some other way.
Piotr Jakubowski
Hmmm ... I did some research and I think you are right that Criteria are not the best way to do this. I will go with indexing the other values. Thanks.
Piotr Jakubowski
+1  A: 

The other way you can do this is to use Filters. A filter can be applied to a Lucene search. Hibernate supports adding filters as annotations and enabling them at run time

Kango_V