`
--晴天--
  • 浏览: 3375 次
社区版块
存档分类
最新评论

Lucene 自定义距离排序

阅读更多

<div class="iteye-blog-content-contain" style="font-size: 14px">

 

 

 

测试类

package sort.distanceSort;

import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

/**
 * @author
 * @Description TODO
 */
public class DistanceSortingTest{
    private RAMDirectory directory;
    private IndexSearcher searcher;
    private Query query;
    public void setUp() throws IOException{
        directory=new RAMDirectory();
        IndexWriter writer=new IndexWriter(directory,
                new IndexWriterConfig(Version.LUCENE_43,
                        new StandardAnalyzer(Version.LUCENE_43)));
        addPoint(writer, "El", "Charro", 1, 2);
        addPoint(writer, "Cafe Poca Cosa", "restaurant", 5, 9);
        addPoint(writer, "Los Betos", "restaurant", 9, 6);
        addPoint(writer, "Nico's Taco Shop", "restaurant", 3, 8);
        addPoint(writer, "Nico's Taco Shopa", "restaurant", 1, 8);
        writer.close();
        searcher=new IndexSearcher(DirectoryReader.open(directory));
        query=new TermQuery(new Term("type","restaurant"));
        System.out.println(query);
    }
   
    private void addPoint(IndexWriter writer,String name,String type,int x,int y )
        throws IOException{
        Document doc=new Document();
        Store yes=Store.YES;
        doc.add(new StringField("name", name, yes));
        doc.add(new StringField("type", type, yes));
        doc.add(new IntField("x", x, yes));
        doc.add(new IntField("y", y, yes));
        writer.addDocument(doc);
    }
    public void testNearestRestaurantToHome() throws IOException{
        Sort sort=new Sort(new SortField("location", new DistanceComparatorSource(0, 0)));
        TopDocs hits=searcher.search(query,10,sort);
        ScoreDoc[] sds=hits.scoreDocs;
        for(ScoreDoc sd:sds){
            System.out.println( searcher.doc(sd.doc).get("name"));
        }
    }
    public static void main(String[] args) throws IOException {
        DistanceSortingTest d=new DistanceSortingTest();
        d.setUp();
        d.testNearestRestaurantToHome();
    }
}

自定义排序类

 

package sort.distanceSort;

import java.io.IOException;

import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.search.FieldCache;
import org.apache.lucene.search.FieldCache.Ints;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;

/**
 * @author
 * @Description TODO
 */
public class DistanceComparatorSource extends FieldComparatorSource{
    private int x;
    private int y;
    public DistanceComparatorSource(int x,int y){
        this.x=x;
        this.y=y;
    }
    /* (non-Javadoc)
     * @see org.apache.lucene.search.FieldComparatorSource#newComparator(java.lang.String, int, int, boolean)
     */
    @Override
    public FieldComparator<?> newComparator(String fieldName, int numHits,
            int sortPos, boolean reversed) throws IOException {
        // TODO Auto-generated method stub
        return new DistanceScoreDocLookupComparator(fieldName, numHits);
    }
   
    private class DistanceScoreDocLookupComparator extends FieldComparator{
        private Ints xDoc,yDoc;
        private float[] value;
        private float bottom;
        String fieldName;
       
        public DistanceScoreDocLookupComparator(String fidldName,int numHits){
            value=new float[numHits];
            this.fieldName=fidldName;
        }
       
        /* (non-Javadoc)
         * 传入新的AtomicReaderContext 所有的后续的docIDs都会关联到当前的reader(
         *如果您需要将其映射到一个顶级docID您必须添加docBase)
         *context 当前reader的上下文环境
         *Returns  比较器需要用到这个实例,大多数比较器都是返回当前实例,夸segment的重用当前实例
         *
         */
        @Override
        public FieldComparator setNextReader(AtomicReaderContext context)
                throws IOException {
            xDoc=FieldCache.DEFAULT.getInts(context.reader(), "x", false);
            yDoc=FieldCache.DEFAULT.getInts(context.reader(), "y", false);
            return this;
        }
   
       
        @Override
        public int compare(int slot1, int slot2) {
            if(value[slot1]<value[slot2])return -1;
            if(value[slot1]>value[slot2])return 1;
            return 0;
        }

        /* (non-Javadoc)
         * 设置 最底位置,即 进到对比队列中的最小值(排在末尾的);
         */
        @Override
        public void setBottom(int slot) {
            bottom=value[slot];
        }

        /* (non-Javadoc)
         * 与文档进行底部比对,只有在setBottom 之后才会调用,与 compare(int,int)功能相同
         * 对于一次命中相对较多的搜索中,这个方法会成为一个调用热点。(是到目前为止调用最为频繁的一个方法)
         */
        @Override
        public int compareBottom(int doc) throws IOException {
            float docDistance=getDistance(doc);
            if(bottom<docDistance)return -1;
            if(bottom>docDistance)return 1;
            return 0;
        }

        /* (non-Javadoc)
         * 当一个命中结果具有争议性的时候会调用这个方法,你需要复制任何一个与文档相关的状态
         * 在之后会再次比对,并放入指定的位置
         */
        @Override
        public void copy(int slot, int doc) throws IOException {
            value[slot]=getDistance(doc);
        }

        public float getDistance(int doc){
            int deltax=xDoc.get(doc)-x;
            int deltay=yDoc.get(doc)-y;
            return (float)Math.sqrt(deltax*deltax+deltay*deltay);
        }
       
        /* (non-Javadoc)
         * 返回当前位置的实际值
         */
        @Override
        public Object value(int slot) {
            return Float.valueOf(value[slot]);
        }

        /* (non-Javadoc)
         * 如果 doc的值小于给定值返回负数
         */
        @Override
        public int compareDocToValue(int doc, Object value) throws IOException {
            return 0;
        }
       
    }
}

 

</div>

 

分享到:
评论

相关推荐

    lucene4.3 按坐标距离排序

    5. **Sorting**:在Lucene中,我们可以自定义排序规则,包括基于地理位置的距离排序。这可以通过实现`SortComparatorSource`接口来自定义比较器,或者使用`FieldComparatorSource`来创建一个基于特定字段(如地理...

    Lucene0之结果排序.pdf

    通过Sort对象可定制排序,如改变文档的Boost值或使用自定义的Similarity方法。Boost值可以在文档级别或字段级别设置,以影响文档的排名。文档Boosting乘以Field-Boosting来计算最终的加权值,如果未特别设置,通常为...

    lucene地理位置搜索所用jar包

    描述中提到的“lucene地理位置搜索并排序”,是指利用Lucene的扩展功能,对包含地理坐标的数据进行搜索,并根据这些坐标进行距离排序。这对于开发Android应用程序尤其有用,因为许多移动应用需要基于用户位置提供...

    lucene拼写纠错代码didyoumean

    - **排序建议**:Lucene会根据编辑距离等指标对建议进行排序,最接近的正确拼写排在前面。 - **应用DidYouMean**:在搜索结果中,可以显示“Did you mean...?”提示,推荐用户更正拼写。 3. **优化与扩展**: - ...

    lucene4.0实例

    3. 排序(Sorting):根据字段值进行排序,不仅可以按相关性排序,还可以按自定义的字段值进行排序。 4. 高亮显示(Highlighting):在搜索结果中高亮显示匹配的关键词。 5. 基于地理位置的搜索:通过Geospatial ...

    Lucene 原理与代码分析完整版

    3. 结果排序:根据评分对匹配结果进行排序,返回最相关的文档。 四、Lucene高级特性 1. 布尔查询:支持AND、OR、NOT等布尔运算符组合查询。 2. 范围查询:支持按数值或日期范围进行筛选。 3. 近似查询:模糊搜索,...

    lucene高级智能查询小案例

    除了基础查询,Lucene还支持更复杂的表达式,例如使用FunctionQuery进行基于文档属性的排序,或者使用CustomScoreQuery自定义评分规则。这些特性使得Lucene可以处理复杂的查询场景,比如根据用户评分、发布日期等...

    Lucene In Action

    - **近邻词查询**:查找包含一组单词且它们在文档中的距离不超过指定阈值的结果。 - **模糊查询**:允许一定程度上的拼写错误,提高搜索结果的相关性。 - **扩展搜索功能的方法**: - **自定义分析器**:通过...

    lucene 编程.

    4. 自定义评分函数:可以编写自定义的评分策略,实现更复杂的排名逻辑。 5. 分片与分布式搜索:通过分片技术适应大数据量场景,实现分布式搜索。 五、扩展与应用 1. Solr:基于Lucene的企业级搜索服务器,提供Web...

    solr自定义评分组件demo.zip

    这可能包括Solr的客户端库、Lucene库以及其他的Java库,这些库将帮助我们编写和测试自定义评分组件。 `pom.zip`可能是项目打包的结果,包含了一个完整的Maven项目结构,解压后可以导入到IDE中进行开发。通常,你会...

    Local Lucene-开源

    4. 距离排序(Distance Sorting):搜索结果可以根据与查询点的距离进行排序,让用户优先看到最近的相关信息。 5. 高效的空间操作:Local Lucene优化了空间查询的性能,例如使用启发式方法或缓存策略来减少不必要的...

    solr-jars.zip

    10. **Spatial Search(空间搜索)**:Solr 还支持地理位置数据的搜索,允许根据地理坐标进行范围查询和距离排序。 压缩包 "solr-jars.zip" 中的 JAR 文件很可能包含了 Solr 和 Lucene 的核心库,这些库可能包括...

    Fuzzy-Information-Retrieval-Search:基于模糊信息检索的搜索引擎,在查询中包含拼写错误。 它已在 Java 和 Lucene 中实现

    4. **结果排序**:根据查询词与文档的模糊匹配程度进行结果排序。 5. **性能优化**:可能涉及缓存策略、内存管理等,以确保大规模数据下的高效检索。 通过这个项目,开发者可以学习如何在实际应用中结合 Java 和 ...

    hibernate-search-4.5.2.Final-dist.zip

    5. 排序和评分:可以基于各种因素(如相关性、距离等)对搜索结果进行排序和评分。 6. 分页和分组:支持分页查询和基于搜索结果的分组,方便数据展示和分析。 四、使用示例 创建一个简单的索引并执行搜索: ```...

    querydsl使用文档

    - 集成空间数据库查询操作,例如如何过滤距离、空间关系查询等。 8. **Lucene查询** - 介绍了Querydsl与全文搜索引擎Lucene的集成使用方法。 9. **Hibernate Search查询** - 详细说明了Querydsl与Hibernate ...

    Solr服务器

    7. **地理位置搜索**:Solr支持地理位置索引和搜索,可以方便地搜索到附近的地点或根据距离排序结果。 8. **自定义插件**:Solr允许开发者编写自己的分析器、查询解析器、过滤器等插件,以满足特定的业务需求。 在...

    solr7.5官方文档doc加pdf格式

    3. **排序与评分**:根据相关性对搜索结果进行排序,可以通过自定义评分函数实现更复杂的排名策略。 4. **多字段搜索**:支持在一个文档中多个字段的搜索,用户可以指定权重,使某些字段的匹配度更重要。 5. ** ...

Global site tag (gtag.js) - Google Analytics