天天看點

解決lucene範圍搜尋中的TooManyClauses exception

上周在使用範圍搜尋時又遇到問題 ,程式抛出TooManyClauses  exception。後來才發現lucene将範圍搜尋轉化為精确比對,每個比對對應一個clause,是以如果你的範圍如果包含超過1024個索引值,程式就會抛錯

由此想到3種方案

1)

既然lucene限制了clause的個數,那麼可以通過

BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE)

改變限制,這個可以解決問題,但有隐患,如果某個範圍的索引特别多,記憶體會有爆掉的危險。

2)根據應用修改索引

比如你有一個範圍是視訊觀看數量(viewedcount) 1000-10000,那麼你可以将這個範圍内的所有的視訊定為一個值(viewedcountlevel),也就是應用的每個搜尋範圍定為一個值,一個應用了不起10個範圍,那麼對範圍檔次建索引,到時候搜的根據 viewedcountlevel而不是viewedcount,将範圍搜尋以應用的角度轉化為精确搜

3)使用filter

比如産生一個RangeFilter

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

if  (advancedSearchVO.getViewedRank()  >   0 )  ... {

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

   if (advancedSearchVO.getViewedRank() == 1) ...{

解決lucene範圍搜尋中的TooManyClauses exception

       return new RangeFilter("viewedcount", "0000000000",

解決lucene範圍搜尋中的TooManyClauses exception

      "0000000100", true, true);

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

   } else if (advancedSearchVO.getViewedRank() == 2) ...{

解決lucene範圍搜尋中的TooManyClauses exception

       return new RangeFilter("viewedcount", "0000000100",

解決lucene範圍搜尋中的TooManyClauses exception

      "0000001000", true, true);

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

   } else if (advancedSearchVO.getViewedRank() == 3) ...{

解決lucene範圍搜尋中的TooManyClauses exception

       return new RangeFilter("viewedcount", "0000001000",

解決lucene範圍搜尋中的TooManyClauses exception

      "0000010000", true, true);

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

   } else if (advancedSearchVO.getViewedRank() == 4) ...{

解決lucene範圍搜尋中的TooManyClauses exception

      return  new RangeFilter("viewedcount", "0000010000",

解決lucene範圍搜尋中的TooManyClauses exception

      "0150000000", true, true);

解決lucene範圍搜尋中的TooManyClauses exception

   }

解決lucene範圍搜尋中的TooManyClauses exception

  }

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

再使用

解決lucene範圍搜尋中的TooManyClauses exception

IndexSearch.search(Query query,Filter filter),

解決lucene範圍搜尋中的TooManyClauses exception

個人比較喜歡最後一種方案,第一種有潛在的危險,第二種又有些脆弱(索引受應用影響大,不穩定),最後一種比較折中一點

前面所說的咚咚确實解決了一個filter的問題,如果你有多個範圍搜尋,也就是說通常你需要多個filter, filter如何嵌套?

首先建立一個filterlist

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

public  List buildFilterList(ISearchVO searchVO)  ... {

解決lucene範圍搜尋中的TooManyClauses exception

        List filterList = new ArrayList();

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

        ..........................                                  

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

    if (advancedSearchVO.getViewedRank() > 0) ...{

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

            if (advancedSearchVO.getViewedRank() == 1) ...{

解決lucene範圍搜尋中的TooManyClauses exception

                    filterList.add(new RangeFilter("viewedcount", "0000000000",

解決lucene範圍搜尋中的TooManyClauses exception

                        "0000000100", true, true));

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

            } else if (advancedSearchVO.getViewedRank() == 2) ...{

解決lucene範圍搜尋中的TooManyClauses exception

                   filterList.add(new RangeFilter("viewedcount", "0000000100",

解決lucene範圍搜尋中的TooManyClauses exception

                        "0000001000", true, true));

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

            } else if (advancedSearchVO.getViewedRank() == 3) ...{

解決lucene範圍搜尋中的TooManyClauses exception

                   filterList.add(new RangeFilter("viewedcount", "0000001000",

解決lucene範圍搜尋中的TooManyClauses exception

                        "0000010000", true, true));

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

            } else if (advancedSearchVO.getViewedRank() == 4) ...{

解決lucene範圍搜尋中的TooManyClauses exception

                   filterList.add(new RangeFilter("viewedcount", "0000010000",

解決lucene範圍搜尋中的TooManyClauses exception

                        "0150000000", true, true));

解決lucene範圍搜尋中的TooManyClauses exception

            }

解決lucene範圍搜尋中的TooManyClauses exception

        }

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

        ...........................

解決lucene範圍搜尋中的TooManyClauses exception

        return filterList;

解決lucene範圍搜尋中的TooManyClauses exception

    }

然後嵌套

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

public  Query buildFilteredQuery(List filterlist, Query query)  ... {

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

        if (filterlist == null || filterlist.size() < 1) ...{

解決lucene範圍搜尋中的TooManyClauses exception

            return query;

解決lucene範圍搜尋中的TooManyClauses exception

        }

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

        FilteredQuery filteredQuery = null;

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

        for (int i = 0; i < filterlist.size(); i++) ...{

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

            if (i == 0) ...{

解決lucene範圍搜尋中的TooManyClauses exception

                filteredQuery = new FilteredQuery(query, (Filter) filterlist

解決lucene範圍搜尋中的TooManyClauses exception

                        .get(i));

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

            } else ...{

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

                filteredQuery = new FilteredQuery(filteredQuery,

解決lucene範圍搜尋中的TooManyClauses exception

                        (Filter) filterlist.get(i));

解決lucene範圍搜尋中的TooManyClauses exception

            }

解決lucene範圍搜尋中的TooManyClauses exception

        }

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

        return filteredQuery;

解決lucene範圍搜尋中的TooManyClauses exception
解決lucene範圍搜尋中的TooManyClauses exception

    }

最後

解決lucene範圍搜尋中的TooManyClauses exception

query  =  buildQuery();

解決lucene範圍搜尋中的TooManyClauses exception

。。。。

解決lucene範圍搜尋中的TooManyClauses exception

query  =  buildFilteredQuery( this .buildFilterList(searchVO), query);

解決lucene範圍搜尋中的TooManyClauses exception

Hits hits  =  searcher.search(query, sort);

解決lucene範圍搜尋中的TooManyClauses exception

。。。。

繼續閱讀