compass in studing

仉磊
2023-12-01

 1.Compass::Spring

Compass::Spring aim is to provide closer integration with the springframework.

Compass::Spring provides the ability to expose Compass as a Spring bean from an application context file.
Application objects that need to access Compass will obtain a reference to a pre-defined instance via bean
references. The following is an example of a Spring XML application context definition configuring Compass:
<beans>
...
<bean id="compass"    class="org.compass.spring.LocalCompassBean">
    <property name="resourceLocations">
        <list>
            <value>classpath:org/compass/spring/test/A.cpm.xml</value>
        </list>
    </property>
    <property name="compassSettings">
        <props>
            <prop key="compass.engine.connection">
                target/testindex
            </prop>
            <!-- This is the default transaction handling (just explicitly setting it) -->
            <prop key="compass.transaction.factory">
                org.compass.core.transaction.LocalTransactionFactory
            </prop>
        </props>
    </property>
</bean>
...
</beans>

●Spring AOP

Compass provides a set of Spring AOP Advices which helps to mirror data changes done within a Spring
powered application. For applications with a data source or a tool with no gps device that works with it (or it
does not have mirroring capabilities - like iBatis), the mirror advices can make synchronizing changes made to
the data source and Compass index simpler.

Advices
The AOP support comes with three advices: CompassCreateAdvice, CompassSaveAdvice, and
CompassDeleteAdvice.
They can create, save, or delete a data Object respectively. The advices are of type
AfterReturningAdvice, and will persist the change to the index after the method proxied/adviced returns.
The data object that will be used to be created/saved/deleted can be one of the adviced method parameters
(using the parameterIndex property), or it's return value (setting the useReturnValue to true).

Dao Sample
The following is an example using Spring AOP to proxy the dao layer. The Dao layer usually acts as an
abstraction layer on top of the actual data source interaction code. It is one of the most common places where
the Compass advices can be applied . The assumption here is that
the Dao have create/save/delete methods.

<beans>
...
<bean id="compass" class="org.compass.spring.LocalCompassBean">
... // configure a compass instance
</bean>
<!-- define the daos -->
<bean id="userDao" class="eg.UserDaoImpl">
...
</bean>
<bean id="contactDao" class="eg.ContactDaoImpl">
...
</bean>

<!-- Definen the advisors -->
<bean id="compassCreateAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
  <property name="advice">
    <bean class="org.compass.spring.aop.CompassCreateAdvice">
      <property name="compass" ref="compass" />
    </bean>
  </property>
  <property name="pattern" value=".*create" />
</bean>

<bean id="compassSaveAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<bean class="org.compass.spring.aop.CompassSaveAdvice">
<property name="compass" ref="compass" />
</bean>
</property>
<property name="pattern" value=".*save" />

</bean>
<bean id="compassDeleteAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<bean class="org.compass.spring.aop.CompassDeleteAdvice">
<property name="compass" ref="compass" />
</bean>
</property>
<property name="pattern" value=".*delete" />
</bean>

<!-- Auto proxy the daos -->
<bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="beanNames"><value>userDao, contactDao</value></property>
  <property name="interceptorNames">
    <list>
      <value>compassCreateAdvisor</value>
      <value>compassSaveAdvisor</value>
      <value>compassDeleteAdvisor</value>
    </list>
  </property>
</bean>
...
</beans>

2.Compass::Gps

Compass::Gps provides integration with different indexable data sources using two concepts: CompassGps and CompassGpsDevice. Both the interfaces are very abstract, since different data sources are usually different in the way they work or the API they expose.
A device is considered to be any type of indexable data source imaginable , from a database (maybe through the use of an ORM mapping tool), file system, ftp site, or a web site.
The main contract that a device is required to provide is the ability to index it's data (using the index() operation). You can think of it as batch indexing the datasource data, providing access for future search queries.
An additional possible operation that a device can implement is mirror data changes, either actively or passively.
When performing the index operation, it is very important NOT to perform it within an already running transaction.
Compass::Gps is built on top of Compass::Core, utilizing all it's features such as transactions (including the important batch_insert level for batch indexing), OSEM, and the simple API that comes with Compass::Core.
 
●CompassGps
CompassGps is the main interface of Compass::Gps. It holds a list of CompassGpsDevice s , and manages their lifecycle.
CompassGpsInterfaceDevice is an extension of CompassGps , and provides the needed abstration between the Compass instance/s and the given devices. Every implementation of a CompassGps must also implement the CompassGpsInterfaceDevice. Compass::Gps comes with two implementations of CompassGps:
SingleCompassGps
Holds a single Compass instance. The Compass instance is used for both the index operation and the mirror operation.
DualCompassGps
Holds two Compass instances. One, called indexCompass is responsible for index operation. The other, called mirrorCompass is responsible for mirror operations.
如果ORM使用的是iBatis,那么下面是一个用SqlMapClient (iBatis) Gps Device的配置例子(spring definition):
 <bean id="iBatisGpsDevice"
  class="org.compass.gps.device.ibatis.SqlMapClientGpsDevice">
  <property name="name" value="ibatis" />
  <property name="sqlMapClient" ref="sqlMapClient" />
  <property name="selectStatementsIds">
   <value>getStores</value>
  </property>
 </bean>
 <bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps"
  init-method="start" destroy-method="stop">
  <property name="compass">
   <ref bean="compass" />
  </property>
  <property name="gpsDevices">
   <list>                                    <!-- It holds a list of CompassGpsDevices -->
    <bean class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">
     <property name="gpsDevice" ref="iBatisGpsDevice" />
    </bean>
   </list>
  </property>
 </bean>
3.应用CompassTemplate
 <bean id="compassTemplate" class="org.compass.core.CompassTemplate">
  <property name="compass">
   <ref bean="compass"/>
  </property>
 </bean
4. 配置搜索类
  <bean id="searchEngineManager" class="com.xxxx.search.impl.SearchEngineManagerImpl">
     <property name="compassGps" ref=" compassGps"/>
     <property name="compassTemplate" ref=" compassTemplate"/>
  </bean>
5. 实现搜索类(这里提供index()和search()两个方法)
package com.xxxx.search.impl;
import org.compass.core.CompassCallback;
import org.compass.core.CompassDetachedHits;
import org.compass.core.CompassException;
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.gps.CompassGps;
import com.xxxx.search.SearchEngineManager;
import com.xxxx.search.model.SearchResults;
import com.xxxx.util.SearchCommand;
public class SearchEngineManagerImpl implements SearchEngineManager {
 private CompassGps compassGps;
 private CompassTemplate compassTemplate;
 public void setCompassTemplate(CompassTemplate compassTemplate) {
  this.compassTemplate = compassTemplate;
 }
 public void setCompassGps(CompassGps compassGps) {
  this.compassGps = compassGps;
 }
 public void index() {
  this.compassGps.index();
 }
 public SearchResults search(final SearchCommand searchCommand) {
  SearchResults searchResults;
  searchResults = (SearchResults) compassTemplate
    .execute(
      CompassTransaction.TransactionIsolation.READ_ONLY_READ_COMMITTED,
      new CompassCallback() {
       public Object doInCompass(CompassSession session)
         throws CompassException {
        return performSearch(searchCommand, session);
       }
      });
  return searchResults;
 }
 protected SearchResults performSearch(
   SearchCommand searchCommand, CompassSession session) {
  int iPageSize, page, hitsLength, from, to, pageCount;
  long time = System.currentTimeMillis();
  CompassQuery query = buildQuery(searchCommand, session);
  CompassHits hits = query.hits();
  CompassDetachedHits detachedHits;
  iPageSize = searchCommand.getPageSize().intValue();
  page = 0;
  hitsLength = hits.getLength();
  if (hitsLength == 0) {
   SearchResults searchResults = new SearchResults();
   searchResults.setHited(false);
   time = System.currentTimeMillis() - time;
   searchResults.setSearchTime(time);
   return searchResults;
  }
  if (searchCommand.getPage() != null) {
   page = searchCommand.getPage().intValue();
  }
  from = page * iPageSize;
  if (from > hitsLength) {
   from = (hitsLength / iPageSize) * iPageSize;
   to = hitsLength - 1;
   doProcessBeforeDetach(searchCommand, session, hits, from,
     hitsLength % iPageSize);
   detachedHits = hits.detach(from, hitsLength % iPageSize);
  } else if ((from + iPageSize) > hitsLength) {
   to = hitsLength - 1;
   doProcessBeforeDetach(searchCommand, session, hits, from,
     hitsLength % iPageSize);
   detachedHits = hits.detach(from, hitsLength % iPageSize);
  } else {
   to = from + iPageSize - 1;
   doProcessBeforeDetach(searchCommand, session, hits, from, iPageSize);
   detachedHits = hits.detach(from, iPageSize);
  }
  doProcessAfterDetach(searchCommand, session, detachedHits);
  pageCount = (int) Math.ceil((float) hitsLength / iPageSize);
  SearchResults searchResults = new SearchResults();
  searchResults.setHited(true);
  searchResults.setCurrentPageNumber(page+1);
  searchResults.setFrom(from+1);
  searchResults.setTo(to+1);
  searchResults.setHits(detachedHits.getHits());
  searchResults.setHitsLength(hitsLength);
  searchResults.setPageCount(pageCount);
  searchResults.setPageSize(iPageSize);
  time = System.currentTimeMillis() - time;
  searchResults.setSearchTime(time);
  return searchResults;
 }
 /**
  * Acts as an extension point for search controller that wish to build
  * different CompassQueries. <p/> The default implementation uses the
  * session to create a query builder and use the queryString option, i.e.:
  * <code>session.queryBuilder().queryString(searchCommand.getQuery().trim()).toQuery();</code>.
  * <p/> Some other interesting options might be to add sorting to the query,
  * adding other queries using a boolean query, or executing a different
  * query.
  */
 protected CompassQuery buildQuery(SearchCommand searchCommand,
   CompassSession session) {
  return session.queryBuilder().queryString(
    searchCommand.getQuery().trim()).toQuery();
 }
 /**
  * An option to perform any type of processing before the hits are detached.
  */
 protected void doProcessBeforeDetach(SearchCommand searchCommand,
   CompassSession session, CompassHits hits, int from, int size) {
 }
 /**
  * An option to perform any type of processing after the hits are detached.
  */
 protected void doProcessAfterDetach(SearchCommand searchCommand,
   CompassSession session, CompassDetachedHits hits) {
 }
}
上面搜索结果用到了SearchResults类,他包装了搜索结果需要的各种属性及其set(),get()方法
 类似资料:

相关阅读

相关文章

相关问答