Compass 入门指南 2

6、Service层(参考了SpringSide实现)
AdvancedSearchCommand.java

package com.mobilesoft.framework.search.service;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.compass.core.CompassQuery.SortDirection;
import org.compass.core.CompassQuery.SortPropertyType;
import org.compass.core.support.search.CompassSearchCommand;

import org.springframework.util.Assert;

public class AdvancedSearchCommand extends CompassSearchCommand {

    /**
     * 封装基于Compass 的排序参数.
     */
    class CompassSort {

        private String name;

        private SortPropertyType type;

        private SortDirection direction;

        public CompassSort() {
        }

        public CompassSort(String sortParamName, String paramType,
                           boolean isAscend) {
            Assert.isTrue(StringUtils.isNotBlank(sortParamName));
            setName(sortParamName);

            if (“int”.equalsIgnoreCase(paramType)) {
                setType(SortPropertyType.INT);
            } else if (“float”.equalsIgnoreCase(paramType)) {
                setType(SortPropertyType.FLOAT);
            } else if (“string”.equalsIgnoreCase(paramType)) {
                setType(SortPropertyType.STRING);
            } else {
                setType(SortPropertyType.AUTO);
            }

            if (isAscend) {
                setDirection(SortDirection.AUTO);
            } else {
                setDirection(SortDirection.REVERSE);
            }
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public SortPropertyType getType() {
            return type;
        }

        public void setType(SortPropertyType type) {
            this.type = type;
        }

        public SortDirection getDirection() {
            return direction;
        }

        public void setDirection(SortDirection direction) {
            this.direction = direction;
        }
    }

    /**
     * 搜索结果排序表.
     */
    private Set<CompassSort> sortMap = new HashSet<CompassSort>();

    private String[] highlightFields;

    /**
     * @param paramType 现定义了三种类型: int string 以及 float。<br>
     *                  除去这三种外,其他会被自动定义为SortPropertyType.AUTO 具体的可见{@link org.compass.core.CompassQuery.SortPropertyType}
     * @param isAscend 顺序还是倒序排序
     * @see org.compass.core.CompassQuery.SortPropertyType#AUTO
     * @see org.compass.core.CompassQuery.SortPropertyType#INT
     * @see org.compass.core.CompassQuery.SortPropertyType#STRING
     * @see org.compass.core.CompassQuery.SortPropertyType#FLOAT
     * @see org.compass.core.CompassQuery.SortDirection#AUTO
     * @see org.compass.core.CompassQuery.SortDirection#REVERSE
     */
    public void addSort(String sortParamName, String paramType, boolean isAscend) {
        this.sortMap.add(new CompassSort(sortParamName, paramType, isAscend));
    }

    public Set<CompassSort> getSortMap() {
        return sortMap;
    }

    public void setSortMap(Set<CompassSort> sortMap) {
        this.sortMap = sortMap;
    }

    public String[] getHighlightFields() {
        return highlightFields;
    }

    public void setHighlightFields(String[] highlightFields) {
        this.highlightFields = highlightFields;
    }
}
CompassIndexBuilder.java

package com.mobilesoft.framework.search.service;

import org.apache.log4j.Logger;
import org.compass.gps.CompassGps;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
* 通过quartz定时调度定时重建索引或自动随Spring ApplicationContext启动而重建索引的Builder.
* 会启动后延时数秒新开线程调用compassGps.index()函数.
* 默认会在Web应用每次启动时重建索引,可以设置buildIndex属性为false来禁止此功能.
* 也可以不用本Builder, 编写手动调用compassGps.index()的代码.
*
*/
public class CompassIndexBuilder implements InitializingBean {

    private static final Logger log = Logger.getLogger(CompassIndexBuilder.class);

    // 是否需要建立索引,可被设置为false使本Builder失效.
    private boolean buildIndex = false;

    // 索引操作线程延时启动的时间,单位为秒
    private int lazyTime = 10;

    // Compass封装
    private CompassGps compassGps;

    // 索引线程
    private Thread indexThread = new Thread() {

        @Override
        public void run() {
            try {
                Thread.sleep(lazyTime * 1000);

                log.info(“begin compass index…”);
                long beginTime = System.currentTimeMillis();
                // 重建索引.
                // 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引,
                // 索引完成后再进行覆盖.
                compassGps.index();
                long costTime = System.currentTimeMillis() - beginTime;
                log.info(“compss index finished.”);
                log.info(“costed “ + costTime + ” milliseconds”);
            } catch (InterruptedException e) {
                // simply proceed
            }
        }
    };

    /**
     * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程.
     *
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception {
        if (buildIndex) {
            Assert.notNull(compassGps, “CompassIndexBuilder not set CompassGps yet.”);
            indexThread.setDaemon(true);
            indexThread.setName(“Compass Indexer”);
            indexThread.start();
        }
    }

    public void setBuildIndex(boolean buildIndex) {
        this.buildIndex = buildIndex;
    }

    public void setLazyTime(int lazyTime) {
        this.lazyTime = lazyTime;
    }

    public void setCompassGps(CompassGps compassGps) {
        this.compassGps = compassGps;
    }
}
CompassSearchService.java

package com.mobilesoft.framework.search.service;

import org.compass.core.Compass;
import org.compass.core.CompassCallback;
import org.compass.core.CompassDetachedHits;
import org.compass.core.CompassHits;
import org.compass.core.CompassQuery;
import org.compass.core.CompassSession;
import org.compass.core.CompassTemplate;
import org.compass.core.CompassTransaction;
import org.compass.core.support.search.CompassSearchCommand;
import org.compass.core.support.search.CompassSearchResults;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import com.mobilesoft.framework.search.service.AdvancedSearchCommand.CompassSort;
/**
* 仿照 {@link org.compass.spring.web.mvc.CompassSearchController}
* 中的代码,构建了一个Service,方便不使用Spring MVC
*
* @see org.compass.spring.web.mvc.CompassSearchController
* @see org.compass.spring.web.mvc.AbstractCompassCommandController
*/
public class CompassSearchService implements InitializingBean {

    //每页显示的条目数量
    private Integer pageSize = 15;

    private Compass compass;

    private CompassTemplate compassTemplate;

    /**
     * 公开的搜索接口,返回匹配的搜索结果,与
     * {@link org.compass.spring.web.mvc.CompassSearchController#handle(javax.servlet.http.HttpServletRequest,
     *javax.servlet.http.HttpServletResponse,Object,org.springframework.validation.BindException) 处理相似
     *
     * @see org.compass.spring.web.mvc.CompassSearchController#handle(javax.servlet.http.HttpServletRequest,
     *javax.servlet.http.HttpServletResponse,java.lang.Object,org.springframework.validation.BindException)
     */
    public CompassSearchResults search(final CompassSearchCommand command) {
        return (CompassSearchResults) getCompassTemplate().execute(
                CompassTransaction.TransactionIsolation.READ_ONLY_READ_COMMITTED, new CompassCallback() {
            public Object doInCompass(CompassSession session) {
                return performSearch(command, session);
            }
        });
    }

    /**
     * 通过此方法调用搜索引擎,进行结果匹配搜索.
     *
     * @see org.compass.spring.web.mvc.CompassSearchController#performSearch(
     *org.compass.spring.web.mvc.CompassSearchCommand,org.compass.core.CompassSession)
     */
    protected CompassSearchResults performSearch(CompassSearchCommand searchCommand, CompassSession session) {
        long time = System.currentTimeMillis();
        CompassQuery query = buildQuery(searchCommand, session);
        CompassHits hits = query.hits();
        CompassDetachedHits detachedHits;
        CompassSearchResults.Page[] pages = null;
        if (pageSize == null) {
            doProcessBeforeDetach(searchCommand, session, hits, -1, -1);
            detachedHits = hits.detach();
        } else {
            int iPageSize = pageSize;
            int page = 0;
            int hitsLength = hits.getLength();
            if (searchCommand.getPage() != null) {
                page = searchCommand.getPage();
            }
            int from = page * iPageSize;

            if (from > hits.getLength()) {

                // 如果起始的条目大于搜索到的条目
                from = hits.getLength() - iPageSize;
                doProcessBeforeDetach(searchCommand, session, hits, from, hitsLength);
                detachedHits = hits.detach(from, hitsLength);
            } else if ((from + iPageSize) > hitsLength) {

                // 结束的条目大于搜索到的结果
                doProcessBeforeDetach(searchCommand, session, hits, from, hitsLength);
                detachedHits = hits.detach(from, hitsLength);
            } else {

                // 中间的页码,直接取出相应的条目
                doProcessBeforeDetach(searchCommand, session, hits, from, iPageSize);
                detachedHits = hits.detach(from, iPageSize);
            }
            doProcessAfterDetach(searchCommand, session, detachedHits);
            int numberOfPages = (int) Math.ceil((float) hitsLength / iPageSize);
            pages = new CompassSearchResults.Page[numberOfPages];
            for (int i = 0; i < pages.length; i++) {
                pages[i] = new CompassSearchResults.Page();
                pages[i].setFrom(i * iPageSize + 1);
                pages[i].setSize(iPageSize);
                pages[i].setTo((i + 1) * iPageSize);
                if (from >= (pages[i].getFrom() - 1) && from < pages[i].getTo()) {
                    pages[i].setSelected(true);
                } else {
                    pages[i].setSelected(false);
                }
            }
            if (numberOfPages > 0) {
                CompassSearchResults.Page lastPage = pages[numberOfPages - 1];
                if (lastPage.getTo() > hitsLength) {
                    lastPage.setSize(hitsLength - lastPage.getFrom());
                    lastPage.setTo(hitsLength);
                }
            }
        }
        time = System.currentTimeMillis() - time;
        CompassSearchResults searchResults = new CompassSearchResults(detachedHits.getHits(), time, pageSize);
        searchResults.setPages(pages);
        return searchResults;
    }

    /**
     * 构建Lucene搜索器.
     */
    protected CompassQuery buildQuery(CompassSearchCommand searchCommand, CompassSession session) {
        CompassQuery query = session.queryBuilder().queryString(searchCommand.getQuery().trim()).toQuery();

        if (AdvancedSearchCommand.class.isAssignableFrom(searchCommand.getClass())) {
            AdvancedSearchCommand advancedSearchCommand = (AdvancedSearchCommand) searchCommand;

            for (CompassSort sort : advancedSearchCommand.getSortMap()) {
                query.addSort(sort.getName(), sort.getType(), sort.getDirection());
            }
        }
        return query;
    }

    /**
     * 在detach 之前,可以做一些操作。比如highlighting…
     *
     * @param from 需要注意的是,如果pageSize 没有指定,那么这里传入的参数为-1
     */
    protected void doProcessBeforeDetach(CompassSearchCommand searchCommand, CompassSession session, CompassHits hits,
                                         int from, int size) {
        if (AdvancedSearchCommand.class.isAssignableFrom(searchCommand.getClass())) {
            if (from < 0) {
                from = 0;
                size = hits.getLength();
            }
            String[] highlightFields = ((AdvancedSearchCommand) searchCommand).getHighlightFields();

            if (highlightFields == null) {
                return;
            }

            // highlight fields
            for (int i = from; i < size; i++) {
                for (String highlightField : highlightFields) {
                    hits.highlighter(i).fragment(highlightField);
                }
            }
        }
    }

    /**
     * An option to perform any type of processing before the hits are detached.
     */
    protected void doProcessAfterDetach(CompassSearchCommand searchCommand, CompassSession session,
                                        CompassDetachedHits hits) {

    }

    public void afterPropertiesSet() throws Exception {
        Assert.notNull(compass, “Must set compass property”);
        this.compassTemplate = new CompassTemplate(compass);
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public void setCompass(Compass compass) {
        this.compass = compass;
    }

    protected CompassTemplate getCompassTemplate() {
        return this.compassTemplate;
    }

}
8、Model层

@SearchableId 声明Document的id列;

@SearchableProperty 声明要索引的field;

@SearchableComponent 声明要索引的其他关联对象。

Article.java

package com.mobilesoft.esales.model;

import java.util.Date;

import org.compass.annotations.Searchable;
import org.compass.annotations.SearchableId;
import org.compass.annotations.SearchableProperty;
import org.compass.core.CompassTemplate;

@Searchable
public class Article implements java.io.Serializable {

    @SearchableId
    private Integer id;
    @SearchableProperty(name=“title”)
    private String title;
    @SearchableProperty(name=“author”)
    private Integer author;
    @SearchableProperty(name=“publishDate”)
    private Date publishDate;

    /** default constructor */
    public Article() {
    }

    /** minimal constructor */
    public Article(String title, Date publishDate) {
        this.title = title;
        this.publishDate = publishDate;
    }

    /** full constructor */
    public Article(String title, Integer author, Date publishDate) {
        this.title = title;
        this.author = author;
        this.publishDate = publishDate;
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return this.title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Integer getAuthor() {
        return this.author;
    }

    public void setAuthor(Integer author) {
        this.author = author;
    }

    public Date getPublishDate() {
        return this.publishDate;
    }

    public void setPublishDate(Date publishDate) {
        this.publishDate = publishDate;
    }

}
Author.java

package com.mobilesoft.esales.model;

import org.compass.annotations.Searchable;
import org.compass.annotations.SearchableId;
import org.compass.annotations.SearchableProperty;
import org.compass.core.CompassTemplate;

@Searchable
public class Author implements java.io.Serializable {

    @SearchableId
    private Integer id;
    @SearchableProperty(name=“username”)
    private String username;
    private String password;
    @SearchableProperty(name=“age”)
    private Short age;

    public Author() {
    }

    /** minimal constructor */
    public Author(String username, String password) {
        this.username = username;
        this.password = password;
    }

    /** full constructor */
    public Author(String username, String password, Short age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

    // Property accessors

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Short getAge() {
        return this.age;
    }

    public void setAge(Short age) {
        this.age = age;
    }

}
9、DAO层
ArticleDAO.java和AuthorDAO.java省略

直接用MyEclipse生成的,没有什么特别的。

10、参考文档
http://www.compass-project.org/docs/1.2.1/reference/html/

The Compass Framework Search made easy.pdf

Compass TSSJS Europe 06.pdf

Hello World Tutorial

InfoQ: Compass: Integrate Search into your apps

InfoQ: Compass: Simplifying and Extending Lucene to Provide Google-like Search

InfoQ: Compass: 在你的应用中集成搜索功能

Compass 指南

http://www.kimchy.org/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值