Search code examples
javalucenebooleanquery

Lucene: Search for documents that dont have specific field


I need to select all documents that dont have specific field, and have right value for one field. I am trying to avoid using "null" string as value for fields that are null, so by lucene, those fields are not saved for those documents.

Document structure looks like this

class familyMember {
   String id;
   String name;
   String parentId; // Id of familyMember object which is parent of this member
}

What I want, is to get all the familyMembers that do not have a parent. So lets say the root of the tree, if you look at it like that.

I tried many ways but this one looks like best way:

if (parentId != null) {
    Query parentIdQuery = new TermQuery(new Term("parentID", parentId.toString()));
    booleanQuery.add(parentIdQuery, BooleanClause.Occur.MUST);
} else {
    QueryParser queryParser = new QueryParser(LUCENE_VERSION, "parentId"), analyzer);
    queryParser.setAllowLeadingWildcard(true);
    Query parentIdQuery = queryParser.parse("%%");
    booleanQuery.add(parentIdQuery, BooleanClause.Occur.MUST_NOT);
}

But for some reason, every time I try this query, I get all familyMambers that don't have a parent except one! And whatever tree structure I try at the end I finish with only ONE member that has a parent....

Does someone know what I am doing wrong or knows better way for finding documents that don't have one field?

I am using booleanQuery because after this I have checking if user wants to more conditions, like get me all members that don't have a parent and has name like "Bill".

EDIT 1: I've tried this one too, but again same problem.

if (parentId != null) {
    Query parentIdQuery = new TermQuery(new Term("parentID", parentId.toString()));
    booleanQuery.add(parentIdQuery, BooleanClause.Occur.MUST);
} else {
    Query parentIdQuery = new TermQuery(new Term("parentID", "%%"));
    booleanQuery.add(parentIdQuery, BooleanClause.Occur.MUST_NOT);
}

Solution

  • Ok, i found solution. Trick was in

    new ConstantScoreQuery(new FieldValueFilter());
    

    Solution:

    if (parentId != null) {
        Query parentIdQuery = new TermQuery(new Term("parentID", parentId.toString()));
        booleanQuery.add(parentIdQuery, BooleanClause.Occur.MUST);
    } else {
        Query parentIdQuery = new ConstantScoreQuery(new FieldValueFilter("parentID", true));
        booleanQuery.add(parentIdQuery, BooleanClause.Occur.MUST);
    

    }