Переглянути джерело

索引实时更新区分事务回退和删除之后重新插入两种情况

sunyj 9 роки тому
батько
коміт
74d9811e9f

+ 31 - 5
search-console/src/main/java/com/uas/search/console/controller/SearchController.java

@@ -12,8 +12,12 @@ import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
+import com.uas.search.console.core.util.ContextUtils;
 import com.uas.search.console.dao.ComponentSimpleInfoDao;
+import com.uas.search.console.model.BrandSimpleInfo;
 import com.uas.search.console.model.ComponentSimpleInfo;
+import com.uas.search.console.model.KindSimpleInfo;
+import com.uas.search.console.service.InnerSearchService;
 import com.uas.search.model.PageParams;
 import com.uas.search.service.SearchService;
 
@@ -30,6 +34,9 @@ public class SearchController {
 	@Autowired
 	private SearchService searchService;
 
+	private InnerSearchService innerSearchService = ContextUtils.getApplicationContext().getBean("searchServiceImpl",
+			InnerSearchService.class);
+
 	@RequestMapping("/kindIds")
 	@ResponseBody
 	public List<Long> seachKindIds(String keyword) {
@@ -132,22 +139,41 @@ public class SearchController {
 	public List<Map<String, Object>> getSimilarKinds(String kindName) {
 		return searchService.getSimilarKinds(kindName);
 	}
-	
+
 	@RequestMapping("/similarLeafKinds")
 	@ResponseBody
-	public List<Map<String, Object>> getSimilarLeafKinds(String kindName){
+	public List<Map<String, Object>> getSimilarLeafKinds(String kindName) {
 		return searchService.getSimilarLeafKinds(kindName);
 	}
 
 	@RequestMapping("/similarKindsByLevel")
 	@ResponseBody
-	public List<Map<String, Object>> getSimilarKindsByLevel(String kindName, Short level){
+	public List<Map<String, Object>> getSimilarKindsByLevel(String kindName, Short level) {
 		return searchService.getSimilarKindsByLevel(kindName, level);
 	}
-	
+
 	@RequestMapping("/similarPropertyValues")
 	@ResponseBody
-	public List<Map<String, String>> getSimilarPropertyValues(Long kindId, Long propertyId, String keyword, Long topNum) {
+	public List<Map<String, String>> getSimilarPropertyValues(Long kindId, Long propertyId, String keyword,
+			Long topNum) {
 		return searchService.getSimilarPropertyValues(kindId, propertyId, keyword, topNum);
 	}
+
+	@RequestMapping("/kind")
+	@ResponseBody
+	public KindSimpleInfo getKind(Long kindId) {
+		return innerSearchService.getKind(kindId);
+	}
+
+	@RequestMapping("/brand")
+	@ResponseBody
+	public BrandSimpleInfo getBrand(Long brandId) {
+		return innerSearchService.getBrand(brandId);
+	}
+
+	@RequestMapping("/component")
+	@ResponseBody
+	public ComponentSimpleInfo getComponent(Long componentId) {
+		return innerSearchService.getComponent(componentId);
+	}
 }

+ 46 - 17
search-console/src/main/java/com/uas/search/console/jms/QueueMessageParser.java

@@ -6,6 +6,7 @@ import org.springframework.stereotype.Service;
 
 import com.alibaba.fastjson.JSONException;
 import com.alibaba.fastjson.JSONObject;
+import com.uas.search.console.core.util.ContextUtils;
 import com.uas.search.console.dao.BrandSimpleInfoDao;
 import com.uas.search.console.dao.ComponentSimpleInfoDao;
 import com.uas.search.console.dao.KindSimpleInfoDao;
@@ -13,6 +14,7 @@ import com.uas.search.console.model.BrandSimpleInfo;
 import com.uas.search.console.model.ComponentSimpleInfo;
 import com.uas.search.console.model.KindSimpleInfo;
 import com.uas.search.console.model.ParsedQueueMessage;
+import com.uas.search.console.service.InnerSearchService;
 import com.uas.search.console.util.SearchConstants;
 
 /**
@@ -33,6 +35,9 @@ public class QueueMessageParser {
 	@Autowired
 	private ComponentSimpleInfoDao componentDao;
 
+	private InnerSearchService innerSearchService = ContextUtils.getApplicationContext().getBean("searchServiceImpl",
+			InnerSearchService.class);
+
 	/**
 	 * 对得到的json消息进行解析
 	 * 
@@ -94,18 +99,29 @@ public class QueueMessageParser {
 		Object[] ids = jsonObject.getJSONArray("ids").toArray();
 		KindSimpleInfo[] kinds = new KindSimpleInfo[ids.length];
 		for (int i = 0; i < ids.length; i++) {
-			Long kindid = Long.parseLong(ids[i].toString());
-			KindSimpleInfo kind = kindDao.findById(kindid);
-			// 对删除操作的事务回退进行处理
-			// (新增操作回退的话,返回的是null,并不影响索引;
-			// 更新回退的话,数据与先前一样,这时更新索引,索引数据并不变)
+			Long kindId = Long.parseLong(ids[i].toString());
+			KindSimpleInfo kind = kindDao.findById(kindId);
+			KindSimpleInfo localKind = innerSearchService.getKind(kindId);
 			if (jsonObject.getString("method").equals("delete")) {
-				// 数据库中该类目仍存在,认为事务回退,不删除索引
+				// 数据库中该类目仍存在
 				if (kind != null) {
-					kind = null;
+					// 与索引中的数据比较
+					// 1. 索引中不存在,返回null,不进行删除操作
+					// 2.索引中存在又与现在的数据相同,说明是事务回退或者是删除之后又重新添加了一条一样的数据
+					// (仅限索引中存储的字段),此时也不必进行操作
+					if (localKind == null || localKind.equals(kind)) {
+						kind = null;
+					}
 				} else {
 					kind = new KindSimpleInfo();
-					kind.setId(kindid);
+					kind.setId(kindId);
+				}
+			}
+			// 新增或更新操作
+			else {
+				// 索引中的数据与数据库一样,不进行操作,认为是事务回退或者删除之后又重新添加了一条一样的数据
+				if (localKind != null && localKind.equals(kind)) {
+					kind = null;
 				}
 			}
 			kinds[i] = kind;
@@ -125,14 +141,21 @@ public class QueueMessageParser {
 		Object[] ids = jsonObject.getJSONArray("ids").toArray();
 		BrandSimpleInfo[] brands = new BrandSimpleInfo[ids.length];
 		for (int i = 0; i < ids.length; i++) {
-			Long brandid = Long.parseLong(ids[i].toString());
-			BrandSimpleInfo brand = brandDao.findById(brandid);
+			Long brandId = Long.parseLong(ids[i].toString());
+			BrandSimpleInfo brand = brandDao.findById(brandId);
+			BrandSimpleInfo localBrand = innerSearchService.getBrand(brandId);
 			if (jsonObject.getString("method").equals("delete")) {
 				if (brand != null) {
-					brand = null;
+					if (localBrand == null || localBrand.equals(brand)) {
+						brand = null;
+					}
 				} else {
 					brand = new BrandSimpleInfo();
-					brand.setId(brandid);
+					brand.setId(brandId);
+				}
+			} else {
+				if (localBrand != null && localBrand.equals(brand)) {
+					brand = null;
 				}
 			}
 			brands[i] = brand;
@@ -152,19 +175,25 @@ public class QueueMessageParser {
 		Object[] ids = jsonObject.getJSONArray("ids").toArray();
 		ComponentSimpleInfo[] components = new ComponentSimpleInfo[ids.length];
 		for (int i = 0; i < ids.length; i++) {
-			Long componentid = Long.parseLong(ids[i].toString());
-			ComponentSimpleInfo component = componentDao.findById(componentid);
+			Long componentId = Long.parseLong(ids[i].toString());
+			ComponentSimpleInfo component = componentDao.findById(componentId);
+			ComponentSimpleInfo localComponent = innerSearchService.getComponent(componentId);
 			if (jsonObject.getString("method").equals("delete")) {
 				if (component != null) {
-					component = null;
+					if (localComponent == null || localComponent.equals(component)) {
+						component = null;
+					}
 				} else {
 					component = new ComponentSimpleInfo();
-					component.setId(componentid);
+					component.setId(componentId);
+				}
+			} else {
+				if (localComponent != null && localComponent.equals(component)) {
+					component = null;
 				}
 			}
 			components[i] = component;
 		}
 		return components;
 	}
-
 }

+ 12 - 0
search-console/src/main/java/com/uas/search/console/model/BrandSimpleInfo.java

@@ -1,6 +1,7 @@
 package com.uas.search.console.model;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -79,6 +80,17 @@ public class BrandSimpleInfo implements Serializable {
 		this.nameEn = nameEn;
 	}
 
+	@Override
+	public boolean equals(Object otherObject) {
+		if (this == otherObject || otherObject == null || getClass() != otherObject.getClass()
+				|| !(otherObject instanceof BrandSimpleInfo)) {
+			return true;
+		}
+		BrandSimpleInfo other = (BrandSimpleInfo) otherObject;
+		return Objects.equals(id, other.getId()) && Objects.equals(uuid, other.getUuid())
+				&& Objects.equals(nameCn, other.getNameCn()) && Objects.equals(nameEn, other.getNameEn());
+	}
+
 	@Override
 	public String toString() {
 		return "BrandSimpleInfo [id=" + id + ", uuid=" + uuid + ", nameCn=" + nameCn + ", nameEn=" + nameEn + "]";

+ 14 - 0
search-console/src/main/java/com/uas/search/console/model/ComponentSimpleInfo.java

@@ -1,6 +1,7 @@
 package com.uas.search.console.model;
 
 import java.io.Serializable;
+import java.util.Objects;
 import java.util.Set;
 
 import javax.persistence.CascadeType;
@@ -115,6 +116,19 @@ public class ComponentSimpleInfo implements Serializable {
 		this.properties = properties;
 	}
 
+	@Override
+	public boolean equals(Object otherObject) {
+		if (this == otherObject || otherObject == null || getClass() != otherObject.getClass()
+				|| !(otherObject instanceof ComponentSimpleInfo)) {
+			return true;
+		}
+		ComponentSimpleInfo other = (ComponentSimpleInfo) otherObject;
+		// 不比较属性值
+		return Objects.equals(id, other.getId()) && Objects.equals(uuid, other.getUuid())
+				&& Objects.equals(code, other.getCode()) && Objects.equals(kindid, other.getKindid())
+				&& Objects.equals(brandid, other.getBrandid());
+	}
+
 	@Override
 	public String toString() {
 		return "ComponentSimpleInfo [id=" + id + ", uuid=" + uuid + ", code=" + code + ", kindid=" + kindid

+ 12 - 0
search-console/src/main/java/com/uas/search/console/model/KindSimpleInfo.java

@@ -1,6 +1,7 @@
 package com.uas.search.console.model;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -79,6 +80,17 @@ public class KindSimpleInfo implements Serializable {
 		this.isLeaf = isLeaf;
 	}
 
+	@Override
+	public boolean equals(Object otherObject) {
+		if (this == otherObject || otherObject == null || getClass() != otherObject.getClass()
+				|| !(otherObject instanceof KindSimpleInfo)) {
+			return true;
+		}
+		KindSimpleInfo other = (KindSimpleInfo) otherObject;
+		return Objects.equals(id, other.getId()) && Objects.equals(nameCn, other.getNameCn())
+				&& Objects.equals(level, other.getLevel()) && Objects.equals(isLeaf, other.getIsLeaf());
+	}
+
 	@Override
 	public String toString() {
 		return "KindSimpleInfo [id=" + id + ", nameCn=" + nameCn + ", level=" + level + ", isLeaf=" + isLeaf + "]";

+ 37 - 0
search-console/src/main/java/com/uas/search/console/service/InnerSearchService.java

@@ -0,0 +1,37 @@
+package com.uas.search.console.service;
+
+import com.uas.search.console.model.BrandSimpleInfo;
+import com.uas.search.console.model.ComponentSimpleInfo;
+import com.uas.search.console.model.KindSimpleInfo;
+
+/**
+ * seaerch-console下自用搜索接口
+ * 
+ * @author sunyj
+ * @since 2016年9月19日 下午7:37:01
+ */
+public interface InnerSearchService {
+	/**
+	 * 根据id获取类目
+	 * 
+	 * @param kindId
+	 * @return
+	 */
+	public KindSimpleInfo getKind(Long kindId);
+
+	/**
+	 * 根据id获取品牌
+	 * 
+	 * @param brandId
+	 * @return
+	 */
+	public BrandSimpleInfo getBrand(Long brandId);
+
+	/**
+	 * 根据id获取器件
+	 * 
+	 * @param componentId
+	 * @return
+	 */
+	public ComponentSimpleInfo getComponent(Long componentId);
+}

+ 17 - 21
search-console/src/main/java/com/uas/search/console/service/impl/IndexServiceImpl.java

@@ -90,7 +90,7 @@ public class IndexServiceImpl implements IndexService {
 		// 清除旧索引
 		File file = new File(SearchConstants.INDEX_DIR);
 		if (file.isDirectory()) {
-			deleteOldIndex(file);
+			clearDir(file);
 		}
 
 		try {
@@ -290,10 +290,7 @@ public class IndexServiceImpl implements IndexService {
 		}
 		Document document = new Document();
 		document.add(new StringField(SearchConstants.BRAND_ID_FIELD, String.valueOf(brand.getId()), Store.YES));
-		String nameCn = brand.getNameCn();
-		if (!StringUtils.isEmpty(nameCn)) {
-			document.add(new TextField(SearchConstants.BRAND_NAMECN_FIELD, nameCn, Store.YES));
-		}
+		document.add(new TextField(SearchConstants.BRAND_NAMECN_FIELD, brand.getNameCn(), Store.YES));
 		String nameEn = brand.getNameEn();
 		if (!StringUtils.isEmpty(nameEn)) {
 			document.add(new TextField(SearchConstants.BRAND_NAMEEN_FIELD, nameEn, Store.YES));
@@ -341,24 +338,23 @@ public class IndexServiceImpl implements IndexService {
 	}
 
 	/**
-	 * 删除原有索引文件
+	 * 清空文件夹
 	 * 
-	 * @param file
+	 * @param dir
 	 */
-	private void deleteOldIndex(File file) {
-		if (file == null) {
+	private void clearDir(File dir) {
+		if (dir == null) {
 			return;
 		}
-		if (file.isDirectory()) {
-			File[] files = file.listFiles();
+		if (dir.isDirectory()) {
+			File[] files = dir.listFiles();
 			for (File f : files) {
-				deleteOldIndex(f);
+				clearDir(f);
 			}
 		}
-
-		file.delete();
+		dir.delete();
 		try {
-			logger.info("deleted " + file.getCanonicalPath());
+			logger.info("Deleted " + dir.getCanonicalPath());
 		} catch (IOException e) {
 			e.printStackTrace();
 		}
@@ -388,7 +384,7 @@ public class IndexServiceImpl implements IndexService {
 					indexWriter.addDocument(document);
 				}
 			} else {
-				logger.error("message parsing failed!");
+				logger.error("Message parsing failed!");
 			}
 			indexWriter.commit();
 		} catch (IOException e) {
@@ -398,7 +394,7 @@ public class IndexServiceImpl implements IndexService {
 		} finally {
 			indexWriterManager.release();
 		}
-		logger.info("saved object... " + obj + "\n");
+		logger.info("Saved... " + obj + "\n");
 	}
 
 	@Override
@@ -430,7 +426,7 @@ public class IndexServiceImpl implements IndexService {
 							new Term(SearchConstants.COMPONENT_ID_FIELD, String.valueOf(component.getId())), document);
 				}
 			} else {
-				logger.error("message parsing failed!");
+				logger.error("Message parsing failed!");
 			}
 			indexWriter.commit();
 		} catch (IOException e) {
@@ -440,7 +436,7 @@ public class IndexServiceImpl implements IndexService {
 		} finally {
 			indexWriterManager.release();
 		}
-		logger.info("updated object... " + obj + "\n");
+		logger.info("Updated... " + obj + "\n");
 	}
 
 	@Override
@@ -460,7 +456,7 @@ public class IndexServiceImpl implements IndexService {
 				indexWriter.deleteDocuments(
 						new Term(SearchConstants.COMPONENT_ID_FIELD, ((ComponentSimpleInfo) obj).getId().toString()));
 			} else {
-				logger.error("message parsing failed!");
+				logger.error("Message parsing failed!");
 			}
 			indexWriter.commit();
 		} catch (IOException e) {
@@ -470,6 +466,6 @@ public class IndexServiceImpl implements IndexService {
 		} finally {
 			indexWriterManager.release();
 		}
-		logger.info("deleted object... " + obj + "\n");
+		logger.info("Deleted... " + obj + "\n");
 	}
 }

+ 134 - 1
search-console/src/main/java/com/uas/search/console/service/impl/SearchServiceImpl.java

@@ -30,6 +30,10 @@ import org.wltea.analyzer.lucene.IKAnalyzer;
 import com.alibaba.fastjson.JSONObject;
 import com.uas.search.console.core.exception.SystemError;
 import com.uas.search.console.core.util.FastjsonUtils;
+import com.uas.search.console.model.BrandSimpleInfo;
+import com.uas.search.console.model.ComponentSimpleInfo;
+import com.uas.search.console.model.KindSimpleInfo;
+import com.uas.search.console.service.InnerSearchService;
 import com.uas.search.console.support.IndexSearcherManager;
 import com.uas.search.console.util.SearchConstants;
 import com.uas.search.model.PageParams;
@@ -42,7 +46,7 @@ import com.uas.search.service.SearchService;
  * @since 2016年8月5日 下午2:21:26
  */
 @Service
-public class SearchServiceImpl implements SearchService {
+public class SearchServiceImpl implements SearchService, InnerSearchService {
 
 	/**
 	 * 默认搜索的最大的记录条数
@@ -749,6 +753,8 @@ public class SearchServiceImpl implements SearchService {
 			removeElements(propertyValues, topNum.intValue());
 		} catch (IOException e) {
 			e.printStackTrace();
+		} finally {
+			searcherManager.release(searcher);
 		}
 
 		List<Map<String, String>> result = new ArrayList<>();
@@ -917,4 +923,131 @@ public class SearchServiceImpl implements SearchService {
 		}
 	}
 
+	@Override
+	public KindSimpleInfo getKind(Long kindId) {
+		String message = "";
+		if (kindId == null) {
+			message = "输入无效:" + kindId;
+			logger.error(message);
+			throw new SystemError(message);
+		}
+		searcherManager.maybeReopen();
+		IndexSearcher indexSearcher = searcherManager.get();
+		if (indexSearcher == null) {
+			message = "获取索引文件失败";
+			logger.error(message);
+			throw new SystemError(message);
+		}
+
+		KindSimpleInfo kind = null;
+		try {
+			TermQuery query = new TermQuery(new Term(SearchConstants.KIND_ID_FIELD, String.valueOf(kindId)));
+			TopDocs topDocs = indexSearcher.search(query, 1);
+			int totalHits = topDocs.totalHits;
+			if (totalHits > 1) {
+				message = "索引中存在不止一个类目:kindId=" + kindId;
+				logger.error(message);
+				throw new SystemError(message);
+			} else if (totalHits == 1) {
+				Document document = indexSearcher.doc(topDocs.scoreDocs[0].doc);
+				kind = new KindSimpleInfo();
+				kind.setId(kindId);
+				kind.setNameCn(document.get(SearchConstants.KIND_NAMECN_FIELD));
+				kind.setIsLeaf(Short.valueOf(document.get(SearchConstants.KIND_ISLEAF_FIELD)));
+				kind.setLevel(Short.valueOf(document.get(SearchConstants.KIND_LEVEL_FIELD)));
+			}
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			searcherManager.release(indexSearcher);
+		}
+		return kind;
+	}
+
+	@Override
+	public BrandSimpleInfo getBrand(Long brandId) {
+		String message = "";
+		if (brandId == null) {
+			message = "输入无效:" + brandId;
+			logger.error(message);
+			throw new SystemError(message);
+		}
+		searcherManager.maybeReopen();
+		IndexSearcher indexSearcher = searcherManager.get();
+		if (indexSearcher == null) {
+			message = "获取索引文件失败";
+			logger.error(message);
+			throw new SystemError(message);
+		}
+
+		BrandSimpleInfo brand = null;
+		try {
+			TermQuery query = new TermQuery(new Term(SearchConstants.BRAND_ID_FIELD, String.valueOf(brandId)));
+			TopDocs topDocs = indexSearcher.search(query, 1);
+			int totalHits = topDocs.totalHits;
+			if (totalHits > 1) {
+				message = "索引中存在不止一个品牌:brandId=" + brandId;
+				logger.error(message);
+				throw new SystemError(message);
+			} else if (totalHits == 1) {
+				Document document = indexSearcher.doc(topDocs.scoreDocs[0].doc);
+				brand = new BrandSimpleInfo();
+				brand.setId(brandId);
+				brand.setNameCn(document.get(SearchConstants.BRAND_NAMECN_FIELD));
+				brand.setNameEn(document.get(SearchConstants.BRAND_NAMEEN_FIELD));
+				brand.setUuid(document.get(SearchConstants.BRAND_UUID_FIELD));
+			}
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			searcherManager.release(indexSearcher);
+		}
+		return brand;
+	}
+
+	@Override
+	public ComponentSimpleInfo getComponent(Long componentId) {
+		String message = "";
+		if (componentId == null) {
+			message = "输入无效:" + componentId;
+			logger.error(message);
+			throw new SystemError(message);
+		}
+		searcherManager.maybeReopen();
+		IndexSearcher indexSearcher = searcherManager.get();
+		if (indexSearcher == null) {
+			message = "获取索引文件失败";
+			logger.error(message);
+			throw new SystemError(message);
+		}
+
+		ComponentSimpleInfo component = null;
+		try {
+			TermQuery query = new TermQuery(new Term(SearchConstants.COMPONENT_ID_FIELD, String.valueOf(componentId)));
+			TopDocs topDocs = indexSearcher.search(query, 1);
+			int totalHits = topDocs.totalHits;
+			if (totalHits > 1) {
+				message = "索引中存在不止一个器件:componentId=" + componentId;
+				logger.error(message);
+				throw new SystemError(message);
+			} else if (totalHits == 1) {
+				Document document = indexSearcher.doc(topDocs.scoreDocs[0].doc);
+				component = new ComponentSimpleInfo();
+				component.setId(componentId);
+				component.setCode(document.get(SearchConstants.COMPONENT_CODE_FIELD));
+				component.setUuid(document.get(SearchConstants.COMPONENT_UUID_FIELD));
+				component.setKindid(Long.valueOf(document.get(SearchConstants.COMPONENT_KINDID_FIELD)));
+				component.setBrandid(Long.valueOf(document.get(SearchConstants.COMPONENT_BRANDID_FIELD)));
+			}
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			searcherManager.release(indexSearcher);
+		}
+		return component;
+	}
+
 }