最后Search Query Sort类(列表6)实现了开发者对结果排序的控制。 public class SearchQuerySort { private List<SearchRank> _ranks; public SearchQuerySort(){ _ranks = new LinkedList<SearchRank>(); } public void addRank(SearchRank rank){ _ranks.add(rank); } @Override public String toString(){ if(_ranks.size() == 0) return null; StringBuffer sb = new StringBuffer(); sb.append("&rank="); boolean first = true; for(SearchRank r : _ranks){ if(!first) sb.append("%2C"); else first = false; sb.append(r); } return sb.toString(); } public static class SearchRank{ private String _name; private boolean _ascending; public SearchRank(){ _ascending = true; } public SearchRank(String name){ _ascending = true; _name = name; } public SearchRank(String name, boolean ascending){ _ascending = ascending; _name = name; } @Override public String toString(){ if(_ascending) return _name; return "-" + _name; } } } Listing 6 Sort control class CloudSearch查询除了将所有的参数汇总到一起,还增加了页码信息和一组返回字段。 这个查询类还提供了一个方法——HTTP查询转换(列表7),将搜索查询的所有部分汇总,并生成能被搜索处理的HTTP字符串。 public String toHttpQuery() throws Exception{ StringBuffer sb = new StringBuffer(); sb.append("?results-type=xml"); if(_size > 0){ sb.append("&size="); sb.append(_size); } if(_start > 0){ sb.append("&start="); sb.append(_start); } if((_fields != null) && (_fields.size() > 0)){ sb.append("&return-fields="); boolean first = true; for(String f : _fields){ if(!first) sb.append("%2C"); else first = false; sb.append(f); } } if(_filter != null){ if(_filter instanceof SearchQueryValueFilter) sb.append("&q="); else sb.append("&bq="); sb.append(URLEncoder.encode(_filter.toString(), "UTF8")); } if((_facets != null) && (_facets.size() > 0)){ for(SearchQueryFacet f : _facets){ sb.append(f); } } if((_sorts != null) && (_sorts.size() > 0)){ for(SearchQuerySort s : _sorts){ sb.append(s); } } return sb.toString(); } Listing 7 Convert to HTTP query method 我们使用Apache HttpComponents来实现与亚马逊云搜索的通信。 测试我们的API我们使用亚马逊提供的IMDB样例来进行验证。首次单元测试(列表8)用于验证我们实现的搜索API。 public class SearchAPITester extends TestCase { private static final String SearchURL = "search-imdb-movies-ab4fpqw4eocczpgsnrtlu4rn7i.us-east- 1.cloudsearch.amazonaws.com"; private CloudSearchClient client; protected void setUp() throws Exception { client = new CloudSearchClient(SearchURL); } protected void tearDown() { client.close(); } public void testSearch() throws Exception{ SearchQueryValueFilter f1 = new SearchQueryValueFilter("title", "star", false, false); SearchQueryValueFilter f11 = new SearchQueryValueFilter("title", "war", false, true); SearchQueryValueFilter f2 = new SearchQueryValueFilter("year", "..2000", true, false); SearchQueryFilterOperation f12 = new SearchQueryFilterOperation(); f12.setOperation(FilterOperation.or); f12.addFilters(f1); f12.addFilters(f11); SearchQueryFilterOperation f3 = new SearchQueryFilterOperation(); f3.addFilters(f12); f3.addFilters(f2); CloudSearchQuery query = new CloudSearchQuery(f3); query.addField("actor"); query.addField("director"); query.addField("title"); query.addField("year"); SearchQueryFacet sf = new SearchQueryFacet("genre", 5, FacetSort.alpha); sf.addConstraint("Drama"); sf.addConstraint("Sci-Fi"); query.addFacet(sf); SearchQuerySort sort = new SearchQuerySort(); SearchRank r1 = new SearchRank("title"); SearchRank r2 = new SearchRank("year", false); sort.addRank(r1); sort.addRank(r2); query.addSort(sort); try { System.out.println("Test 1 "); SearchResults result = client.search(query); System.out.println(result); } catch (Exception e) { e.printStackTrace(); } } } Listing 8 Search API tester |