
cn.leancloud.search.LCSearchQuery Maven / Gradle / Ivy
package cn.leancloud.search;
import cn.leancloud.*;
import cn.leancloud.LCUser;
import cn.leancloud.LCObject;
import cn.leancloud.core.PaasClient;
import cn.leancloud.utils.LCUtils;
import cn.leancloud.utils.LogUtil;
import cn.leancloud.utils.StringUtil;
import io.reactivex.Observable;
import io.reactivex.functions.Function;
import java.util.*;
public class LCSearchQuery {
private static final LCLogger LOGGER = LogUtil.getLogger(LCSearchQuery.class);
public static final String AVSEARCH_HIGHTLIGHT = "highlight_avoscloud_";
public static final String AVSEARCH_APP_URL = "app_url_avoscloud_";
public static final String AVSEARCH_DEEP_LINK = "deep_link_avoscloud_";
public static final String DATA_EXTRA_SEARCH_KEY = "com.avos.avoscloud.search.key";
private String sid;
private int limit = 100;
private int skip = 0;
private String hightlights = null;
private static final String URL = "search/select";
private List fields;
private String queryString;
private String titleAttribute;
private String className;
private int hits;
private String order;
private LCSearchSortBuilder sortBuilder;
private List include;
Class clazz;
/**
* 获取当前的AVSearchSortBuilder对象
*
* @return sort builder.
*/
public LCSearchSortBuilder getSortBuilder() {
return sortBuilder;
}
/**
* 设置查询的AVSearchSortBuilder,使用更丰富的排序选项。
*
* @param sortBuilder sort builder.
*/
public void setSortBuilder(LCSearchSortBuilder sortBuilder) {
this.sortBuilder = sortBuilder;
}
public LCSearchQuery() {
this(null);
}
public LCSearchQuery(String queryString) {
this(queryString, null);
}
public LCSearchQuery(String queryString, Class clazz) {
this.queryString = queryString;
this.clazz = clazz;
this.include = new LinkedList();
if (clazz == null) {
this.className = Transformer.getSubClassName(LCObject.class);
} else {
this.className = Transformer.getSubClassName(clazz);
}
}
/**
* 获取查询的className,默认为null,即包括所有启用了应用内搜索的class
*
* @return class name.
*/
public String getClassName() {
return className;
}
/**
* 设置查询字段列表,以逗号隔开的字符串,例如"a,b,c",表示按照a,b,c三个字段的顺序排序,如果字段前面有负号,表示倒序,例如"a,-b"
*
* @param order order string.
* @return Returns the query, so you can chain this call.
*/
public LCSearchQuery order(String order) {
this.order = order;
return this;
}
/**
* 根据提供的key进行升序排序
*
* @param key 需要排序的key
* @return Returns the query, so you can chain this call.
*/
public LCSearchQuery orderByAscending(String key) {
if (StringUtil.isEmpty(order)) {
order = String.format("%s", key);
} else {
order = String.format("%s,%s", order, key);
}
return this;
}
/**
* 根据提供的key进行降序排序
*
* @param key The key to order by.
* @return Returns the query, so you can chain this call.
*/
public LCSearchQuery orderByDescending(String key) {
if (StringUtil.isEmpty(order)) {
order = String.format("-%s", key);
} else {
order = String.format("%s,-%s", order, key);
}
return this;
}
/**
* Also sorts the results in ascending order by the given key. The previous sort keys have
* precedence over this key.
*
* @param key The key to order by
* @return Returns the query so you can chain this call.
*/
public LCSearchQuery addAscendingOrder(String key) {
if (StringUtil.isEmpty(order)) {
return this.orderByAscending(key);
}
order = String.format("%s,%s", order, key);
return this;
}
/**
* Also sorts the results in descending order by the given key. The previous sort keys have
* precedence over this key.
*
* @param key The key to order by
* @return Returns the query so you can chain this call.
*/
public LCSearchQuery addDescendingOrder(String key) {
if (StringUtil.isEmpty(order)) {
return orderByDescending(key);
}
order = String.format("%s,-%s", order, key);
return this;
}
/**
* 设置查询的className,否则将包括所有启用了应用内搜索的class
*
* @param className class name
*/
public void setClassName(String className) {
this.className = className;
}
/**
* 设置搜索的结果单页大小限制,默认值为100,最大为1000
*
* @param limit pagination limit.
*/
public void setLimit(int limit) {
this.limit = limit;
}
/**
* 获得搜索结果的单页大小限制
*
* @return pagination limit.
*/
public int getLimit() {
return this.limit;
}
/**
* 返回当前返回集合的其实位置
*
* @return current skip.
*/
public int getSkip() {
return skip;
}
/**
* 设置返回集合的起始位置,一般用于分页
*
* @param skip skip value.
*/
public void setSkip(int skip) {
this.skip = skip;
}
/**
* 设置返回的高亮语法,默认为"*"
* 语法规则可以参考 http://www.elasticsearch.org/guide/en/elasticsearch/reference/current
* /search-request-highlighting.html#highlighting-settings
*
* @param hightlights highlight setting.
*/
public void setHightLights(String hightlights) {
this.hightlights = hightlights;
}
/**
* 获取当前设定的语法高亮
*
* @return highlight setting.
*/
public String getHightLights() {
return this.hightlights;
}
public void setFields(List fields) {
this.fields = fields;
}
public List getFields() {
return this.fields;
}
/**
* 设置查询id,通常您都不需要调用这个方法来设置,只要不停调用find就可以实现分页。
* 不过如果需要将查询分页传递到其他Activity,则可能需要通过传递sid来实现。
*
* @param sid search session id.
*/
public void setSid(String sid) {
this.sid = sid;
}
/**
* 获取本次查询的id,注意,它不是返回结果中对象的objectId,而是表示本次AVSearchQuery查询的id
*
* @return search session id.
*/
public String getSid() {
return this.sid;
}
/**
* 此选项为AVOSCloud SearchActivity使用 指定Title所对应的Field
*
* @param titleAttribute title setting.
*/
public void setTitleAttribute(String titleAttribute) {
this.titleAttribute = titleAttribute;
}
/**
* 获取当前指定的title 对应的Field
*
* @return title setting.
*/
public String getTitleAttribute() {
return titleAttribute;
}
/**
* 设置搜索的查询语句。
* 详细语法可以参考http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl
* -query-string-query.html#query-string-syntax
*
* @param query query string.
*/
public void setQueryString(String query) {
if (!((this.queryString == null && query == null) || (this.queryString != null && this.queryString
.equals(query)))) {
this.sid = null;
}
this.queryString = query;
}
public String getQueryString() {
return queryString;
}
public int getHits() {
return this.hits;
}
public void include(String key) {
this.include.add(key);
}
private Map getParameters(String query) {
Map params = new HashMap<>();
params.put("q", query);
if (!StringUtil.isEmpty(sid)) {
params.put("sid", sid);
}
if (!StringUtil.isEmpty(hightlights)) {
params.put("highlights", hightlights);
} else {
params.put("highlights", "*");
}
if (fields != null && fields.size() > 0) {
params.put("fields", StringUtil.join(",", fields));
}
if (limit > 0) {
params.put("limit", String.valueOf(limit));
}
if (skip > 0) {
params.put("skip", String.valueOf(skip));
}
if (!StringUtil.isEmpty(order)) {
params.put("order", order);
}
if (sortBuilder != null) {
params.put("sort", LCUtils.jsonStringFromObjectWithNull(sortBuilder.getSortFields()));
}
if (!include.isEmpty()) {
String value = StringUtil.join(",", include);
params.put("include", value);
}
if (!StringUtil.isEmpty(className)) {
params.put("clazz", className);
}
return params;
}
/**
* execute query in background.
* @return observable instance.
*/
public Observable> findInBackground() {
return this.findInBackground(null);
}
/**
* execute query in background.
* @param asAuthenticatedUser explicit user for request authentication.
* @return observable instance.
*
* in general, this method should be invoked in lean engine.
*/
public Observable> findInBackground(LCUser asAuthenticatedUser) {
return getSearchResult(asAuthenticatedUser, getParameters(queryString));
}
protected Observable> getSearchResult(LCUser asAuthenticatedUser, Map params) {
return PaasClient.getStorageClient().search(asAuthenticatedUser, params).map(new Function>() {
@Override
public List apply(LCSearchResponse result) throws Exception {
return processContent(result);
}
});
}
private List processContent(LCSearchResponse resp) throws Exception {
if (null == resp) {
return Collections.emptyList();
}
this.sid = resp.sid;
this.hits = resp.hits;
List result = new LinkedList();
for (Map item : resp.results) {
if (item != null && !item.isEmpty()) {
LCObject object;
if (clazz == null) {
object = new LCObject(StringUtil.isEmpty(className) ? (String) item.get("className") : className);
} else {
object = clazz.newInstance();
}
if(item.containsKey("_highlight")) {
item.put(AVSEARCH_HIGHTLIGHT, item.get("_highlight"));
item.remove("_highlight");
}
if(item.containsKey("_app_url")) {
item.put(AVSEARCH_APP_URL, item.get("_app_url"));
item.remove("_app_url");
}
if(item.containsKey("_deeplink")) {
item.put(AVSEARCH_DEEP_LINK, item.get("_deeplink"));
item.remove("_deeplink");
}
object.resetServerData(item);
result.add((T) object);
}
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy