Lucene自定义规则范围查询

0x00

  level: 0x04

0x01

  code:

package org.apache.lucene.demo.big.query;

import java.io.IOException;
import java.util.Comparator;

import org.apache.lucene.index.FilteredTermsEnum;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.BytesRef;

public class IpRangeQuery extends MultiTermQuery {

    private String    minIp, maxIp;

    public IpRangeQuery(String field, String minIp, String maxIp) {
        super(field);
        this.minIp = minIp;
        this.maxIp = maxIp;
    }

    @Override
    protected TermsEnum getTermsEnum(Terms terms, AttributeSource atts) throws IOException {
        return new IpRangeTermsEnum(terms.iterator(null));
    }

    private final class IpRangeTermsEnum extends FilteredTermsEnum {
        private Comparator<String>    termComp    = new Comparator<String>() {
                                                                                        @Override
                                                                                        public int compare(String ip1, String ip2) {
                                                                                            if (ip1.equals(ip2))
                                                                                                return 0;
                                                                                            return getIpLong(ip1) - getIpLong(ip2) > 0 ? 1 : -1;
                                                                                        }
                                                                                    };

        private long getIpLong(String ip) {
            long v = 0;
            int startIndex = 0;
            int postion = 0;
            int vBase = 1;
            String ipByte = "";

            for (int i = 0; i < 4; i++) {

                if (i == 3) {
                    ipByte = ip.substring(startIndex, ip.length());
                } else {
                    postion = ip.indexOf(".", startIndex);
                    ipByte = ip.substring(startIndex, postion);
                    startIndex = postion + 1;
                }

                switch (i) {
                case 0:
                    vBase = 1 * 1000 * 1000 * 1000;
                    break;
                case 1:
                    vBase = 1 * 1000 * 1000;
                    break;
                case 2:
                    vBase = 1 * 1000;
                    break;
                default:
                    vBase = 1;
                    break;
                }

                v += Long.valueOf(ipByte) * vBase;
            }

            return v;
        }

        public IpRangeTermsEnum(TermsEnum tenum) {
            super(tenum);
        }

        @Override
        protected final BytesRef nextSeekTerm(BytesRef term) {
            String termStr = term == null ? null : term.utf8ToString();

            if (termStr != null && termComp.compare(termStr, maxIp) > 0)
                return null;

            if (termStr != null && termComp.compare(minIp, termStr) > 0)
                return null;

            return term == null ? new BytesRef(minIp) : term;
        }

        @Override
        protected final AcceptStatus accept(BytesRef term) {
            String termStr = term.utf8ToString();

            if (termComp.compare(termStr, minIp) < 0)
                return AcceptStatus.NO;

            if (termComp.compare(maxIp, termStr) < 0)
                return AcceptStatus.NO;

            return AcceptStatus.YES;

        }
    }

    @Override
    public String toString(String field) {
        return this.field + ":[" + this.minIp + " TO " + this.maxIp + "]";
    }

}

0x02

  参考: TermRangeQuery 和 NumericRangeQuery

posted @ 2015-03-04 17:04  _峰_  阅读(494)  评论(0编辑  收藏  举报