Просмотр исходного кода

update related goods when updating brand

sunyj 8 лет назад
Родитель
Сommit
f0c2ebb3fc

+ 2 - 0
mall-search/src/main/java/com/uas/search/constant/SearchConstants.java

@@ -144,6 +144,8 @@ public class SearchConstants {
     public static final String GOODS_BR_WEIGHT_FIELD = "br_weight";
 	public static final String GOODS_PR_ID_FIELD = "pr_id";
 	public static final String GOODS_PR_PCMPCODE_FIELD = "pr_pcmpcode";
+	// 自动生成的字段,用于唯一区分批次索引
+    public static final String GOODS_PRIMARY_KEY_FIELD = "primary_key";
 
 	// 商城销售订单索引字段的key
 	/**

+ 451 - 406
mall-search/src/main/java/com/uas/search/service/impl/IndexServiceImpl.java

@@ -14,6 +14,7 @@ import com.uas.search.jms.JmsListener;
 import com.uas.search.jms.QueueMessageParser;
 import com.uas.search.model.*;
 import com.uas.search.service.IndexService;
+import com.uas.search.service.SearchService;
 import com.uas.search.support.DownloadHelper;
 import com.uas.search.support.DownloadService;
 import com.uas.search.support.IndexSearcherManager;
@@ -24,6 +25,8 @@ import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,85 +48,69 @@ import static com.uas.search.constant.SearchConstants.GOODS_TABLE_NAME;
 @Service
 public class IndexServiceImpl implements IndexService {
 
+    /**
+     * 从数据库获取数据时的分页大小
+     */
+    public static final int PAGE_SIZE = 1000;
+    /**
+     * 单个文件存储的最大数据数目,需是PAGE_SIZE的整数倍
+     */
+    public static final int SINGLE_FILE_MAX_SIZE = PAGE_SIZE;
+    private static IndexWriterManager indexWriterManager = new IndexWriterManager();
+    private static Logger logger = LoggerFactory.getLogger(IndexServiceImpl.class);
     @Autowired
     private DruidDBConfiguration druidDBConfiguration;
-
-	@Autowired
-	private QueueMessageParser queueMessageParser;
-
-	@Autowired
-	private KindDao kindDao;
-
-	@Autowired
-	private BrandDao brandDao;
-
-	@Autowired
-	private ComponentDao componentDao;
-
+    @Autowired
+    private QueueMessageParser queueMessageParser;
+    @Autowired
+    private KindDao kindDao;
+    @Autowired
+    private BrandDao brandDao;
+    @Autowired
+    private ComponentDao componentDao;
     @Autowired
     private TradeGoodsDao tradeGoodsDao;
+    @Autowired
+    private GoodsDao goodsDao;
+    @Autowired
+    private OrderDao orderDao;
+    @Autowired
+    private OrderInvoiceDao orderInvoiceDao;
+    @Autowired
+    private PurchaseDao purchaseDao;
+    @Autowired
+    private PurchaseInvoiceDao purchaseInvoiceDao;
+    private IndexWriter indexWriter;
+    @Autowired
+    private JmsListener jmsListener;
+    private IndexSearcherManager indexSearcherManager = IndexSearcherManager.getInstance();
+    @Autowired
+    private SearchService searchService;
+    /**
+     * 是否正在创建索引
+     */
+    private boolean creatingIndex = false;
 
-	@Autowired
-	private GoodsDao goodsDao;
-
-	@Autowired
-	private OrderDao orderDao;
-
-	@Autowired
-	private OrderInvoiceDao orderInvoiceDao;
-
-	@Autowired
-	private PurchaseDao purchaseDao;
-
-	@Autowired
-	private PurchaseInvoiceDao purchaseInvoiceDao;
-
-	private IndexWriter indexWriter;
-
-	private static IndexWriterManager indexWriterManager = new IndexWriterManager();
-
-	@Autowired
-	private JmsListener jmsListener;
-
-	private IndexSearcherManager indexSearcherManager = IndexSearcherManager.getInstance();
-
-	/**
-	 * 是否正在创建索引
-	 */
-	private boolean creatingIndex = false;
-
-	/**
-	 * 从数据库获取数据时的分页大小
-	 */
-	public static final int PAGE_SIZE = 1000;
-
-	/**
-	 * 单个文件存储的最大数据数目,需是PAGE_SIZE的整数倍
-	 */
-	public static final int SINGLE_FILE_MAX_SIZE = PAGE_SIZE;
-
-	private static Logger logger = LoggerFactory.getLogger(IndexServiceImpl.class);
-
-	@Override
-	public Long createIndexes(List<String> tableNames, Boolean componentFromFiles) {
-		if (creatingIndex) {
-			throw new IllegalStateException("已存在线程在创建索引,不可重复请求");
-		}
-		creatingIndex = true;
-		// 如果索引实时更新处于开启状态,需要关闭(以免两者同时操作索引出现问题)
-		if (jmsListener.isRunning()) {
-			logger.info("索引实时更新服务正在运行,尝试关闭索引实时更新服务...");
-			jmsListener.stop();
-		}
+    @Override
+    public Long createIndexes(List<String> tableNames, Boolean componentFromFiles) {
+        if (creatingIndex) {
+            throw new IllegalStateException("已存在线程在创建索引,不可重复请求");
+        }
+        creatingIndex = true;
+        // 如果索引实时更新处于开启状态,需要关闭(以免两者同时操作索引出现问题)
+        if (jmsListener.isRunning()) {
+            logger.info("索引实时更新服务正在运行,尝试关闭索引实时更新服务...");
+            jmsListener.stop();
+        }
 
-		if (CollectionUtils.isEmpty(tableNames)) {
-			tableNames = SearchUtils.getTableNames();
-		}
+        if (CollectionUtils.isEmpty(tableNames)) {
+            tableNames = SearchUtils.getTableNames();
+        }
 
-		try {
-			Long startTime = new Date().getTime();
+        try {
+            Long startTime = new Date().getTime();
 
-			for (String tableName : tableNames) {
+            for (String tableName : tableNames) {
                 try {
                     Long start = new Date().getTime();
                     Long size = 0L;
@@ -156,62 +143,61 @@ public class IndexServiceImpl implements IndexService {
                     indexSearcherManager.flushCache(tableName, indexWriter, null);
                     Long end = new Date().getTime();
                     logger.info(String.format("创建%s索引: %s条,耗时%.2fs\n ", tableName, size, (end - start) / 1000.0));
-                }finally {
+                } finally {
                     indexWriterManager.release(tableName);
                 }
             }
 
-			Long endTime = new Date().getTime();
-			logger.info(String.format("索引创建成功, 共用时间%.2fs\n", (endTime - startTime) / 1000.0));
-			return endTime - startTime;
-		} catch (Exception e) {
-			// 防止SQLRecoverableException导致应用终止
-			throw new IllegalStateException("索引创建失败", e);
-		} finally {
-			creatingIndex = false;
-		}
-	}
-
-	/**
-	 * 删除指定表的索引
-	 *
-	 * @param tableName
-	 *            表名
-	 * @throws InterruptedException
-	 * @throws IOException
-	 */
-	private void deleteIndexes(String tableName) throws InterruptedException, IOException {
-		indexWriter = indexWriterManager.get(tableName);
-		logger.info("正在清理旧索引..." + tableName);
-		indexWriter.deleteAll();
-		logger.info("旧索引清理完毕..." + tableName);
-	}
-
-	/**
-	 * 创建类目索引
-	 *
-	 * @return 写入的类目索引数
-	 * @throws IOException
-	 */
-	private Long createKindIndexes() throws IOException {
-		logger.info("正在创建类目索引...");
-		List<Kind> kinds = kindDao.findAll();
-		logger.info("发现数据:" + kinds.size() + "条");
-		return createIndexesWithObjects(kinds.toArray());
-	}
-
-	/**
-	 * 创建品牌索引
-	 *
-	 * @return 写入的品牌索引数
-	 * @throws IOException
-	 */
-	private Long createBrandIndexes() throws IOException {
-		logger.info("正在创建品牌索引...");
-		List<Brand> brands = brandDao.findAll();
-		logger.info("发现数据:" + brands.size() + "条");
-		return createIndexesWithObjects(brands.toArray());
-	}
+            Long endTime = new Date().getTime();
+            logger.info(String.format("索引创建成功, 共用时间%.2fs\n", (endTime - startTime) / 1000.0));
+            return endTime - startTime;
+        } catch (Exception e) {
+            // 防止SQLRecoverableException导致应用终止
+            throw new IllegalStateException("索引创建失败", e);
+        } finally {
+            creatingIndex = false;
+        }
+    }
+
+    /**
+     * 删除指定表的索引
+     *
+     * @param tableName 表名
+     * @throws InterruptedException
+     * @throws IOException
+     */
+    private void deleteIndexes(String tableName) throws InterruptedException, IOException {
+        indexWriter = indexWriterManager.get(tableName);
+        logger.info("正在清理旧索引..." + tableName);
+        indexWriter.deleteAll();
+        logger.info("旧索引清理完毕..." + tableName);
+    }
+
+    /**
+     * 创建类目索引
+     *
+     * @return 写入的类目索引数
+     * @throws IOException
+     */
+    private Long createKindIndexes() throws IOException {
+        logger.info("正在创建类目索引...");
+        List<Kind> kinds = kindDao.findAll();
+        logger.info("发现数据:" + kinds.size() + "条");
+        return createIndexesWithObjects(kinds.toArray());
+    }
+
+    /**
+     * 创建品牌索引
+     *
+     * @return 写入的品牌索引数
+     * @throws IOException
+     */
+    private Long createBrandIndexes() throws IOException {
+        logger.info("正在创建品牌索引...");
+        List<Brand> brands = brandDao.findAll();
+        logger.info("发现数据:" + brands.size() + "条");
+        return createIndexesWithObjects(brands.toArray());
+    }
 
     private Long createComponentIndexesFromFiles() throws IOException {
         logger.info("正在创建器件索引...");
@@ -251,7 +237,7 @@ public class IndexServiceImpl implements IndexService {
         } catch (FileNotFoundException e) {
             logger.error("创建器件索引失败,原因:器件数据文件不存在!");
             return 0L;
-        }  finally {
+        } finally {
             if (bufferedReader != null) {
                 bufferedReader.close();
             }
@@ -259,57 +245,57 @@ public class IndexServiceImpl implements IndexService {
         return size;
     }
 
-	/**
-	 * 创建器件索引,从数据库取数据
-	 *
-	 * @return 写入的器件索引数
-	 * @throws IOException
-	 */
-	public Long createComponentIndexes() throws IOException {
-		logger.info("正在创建器件索引...");
-		Long size = 0L;
-		PageParams params = new PageParams();
-		int page = 1;
-		params.setSize(PAGE_SIZE);
-		params.setPage(page);
-
-		PageInfo info = new PageInfo(params);
-		Page<Component> pageResult = componentDao.findAll(info);
-		long totalElements = pageResult.getTotalElements();
-		logger.info("Number of components: " + totalElements);
-		// 用于记录上次提交索引时的创建进度
-		double recordProgress = 0;
-		while (totalElements > size) {
-			List<Component> components = pageResult.getContent();
-			for (Component component : components) {
-				Document document = ObjectToDocumentUtils.toDocument(component);
-				if (document != null) {
-					indexWriter.addDocument(document);
-				}
-			}
-			size += components.size();
-
-			// 器件索引的创建进度(百分比)
-			double indexProgress = size * 100.0 / totalElements;
-			logger.info(String.format("Component indexed...................%.2f%%", indexProgress));
-			// 每创建5%,提交一次,避免内存耗尽,发生OutOfMemoryError
-			if (indexProgress - recordProgress > 5) {
-				indexWriter.commit();
-				recordProgress = indexProgress;
-			}
-
-			page++;
-			params.setPage(page);
-			info = new PageInfo(params);
-			pageResult = componentDao.findAll(info);
-		}
-		indexWriter.commit();
-		return size;
-	}
-
-	private Long createGoodsIndexesFromFiles() throws IOException {
-		return createGoodsIndexesFromFiles(true);
-	}
+    /**
+     * 创建器件索引,从数据库取数据
+     *
+     * @return 写入的器件索引数
+     * @throws IOException
+     */
+    public Long createComponentIndexes() throws IOException {
+        logger.info("正在创建器件索引...");
+        Long size = 0L;
+        PageParams params = new PageParams();
+        int page = 1;
+        params.setSize(PAGE_SIZE);
+        params.setPage(page);
+
+        PageInfo info = new PageInfo(params);
+        Page<Component> pageResult = componentDao.findAll(info);
+        long totalElements = pageResult.getTotalElements();
+        logger.info("Number of components: " + totalElements);
+        // 用于记录上次提交索引时的创建进度
+        double recordProgress = 0;
+        while (totalElements > size) {
+            List<Component> components = pageResult.getContent();
+            for (Component component : components) {
+                Document document = ObjectToDocumentUtils.toDocument(component);
+                if (document != null) {
+                    indexWriter.addDocument(document);
+                }
+            }
+            size += components.size();
+
+            // 器件索引的创建进度(百分比)
+            double indexProgress = size * 100.0 / totalElements;
+            logger.info(String.format("Component indexed...................%.2f%%", indexProgress));
+            // 每创建5%,提交一次,避免内存耗尽,发生OutOfMemoryError
+            if (indexProgress - recordProgress > 5) {
+                indexWriter.commit();
+                recordProgress = indexProgress;
+            }
+
+            page++;
+            params.setPage(page);
+            info = new PageInfo(params);
+            pageResult = componentDao.findAll(info);
+        }
+        indexWriter.commit();
+        return size;
+    }
+
+    private Long createGoodsIndexesFromFiles() throws IOException {
+        return createGoodsIndexesFromFiles(true);
+    }
 
     /**
      * 创建批次索引
@@ -319,16 +305,16 @@ public class IndexServiceImpl implements IndexService {
      * @throws IOException
      */
     private Long createGoodsIndexesFromFiles(boolean updateFromDbAfterCreating) throws IOException {
-        if(updateFromDbAfterCreating){
+        if (updateFromDbAfterCreating) {
             logger.info("正在创建批次索引...");
-        }else{
+        } else {
             logger.info("正在更新批次索引...");
         }
         Long size = 0L;
-        BufferedReader bufferedReader=null;
+        BufferedReader bufferedReader = null;
         try {
             // 如果创建后需要更新本地索引,说明还未创建索引,本次便是在进行创建索引,需要转换器件数据,用来建索引
-            if(updateFromDbAfterCreating){
+            if (updateFromDbAfterCreating) {
                 convertGoodsFromComponent();
             }
             // 从本地路径读取批次数据
@@ -382,7 +368,7 @@ public class IndexServiceImpl implements IndexService {
             }
         }
         // 如果需要从批次表获取数据,更新本地索引
-        if(updateFromDbAfterCreating){
+        if (updateFromDbAfterCreating) {
             try {
                 multiDownloadGoods(null, null, null, DownloadHelper.ValidateResult.CURRENT);
                 createGoodsIndexesFromFiles(false);
@@ -412,7 +398,12 @@ public class IndexServiceImpl implements IndexService {
                 logger.info("转换批次失败,原因:器件数据文件不存在!");
                 return 0L;
             }
-            FileUtils.deleteSubFiles(new File(goodsDataPath));
+            File goodsDataDir = new File(goodsDataPath);
+            if (!goodsDataDir.exists()) {
+                goodsDataDir.mkdirs();
+            } else {
+                FileUtils.deleteSubFiles(goodsDataDir);
+            }
             int fileIndex = 1;
             for (File file : files) {
                 logger.info("读取器件文件: " + file.getName());
@@ -442,8 +433,8 @@ public class IndexServiceImpl implements IndexService {
             return endStartTime - startTime;
         } catch (Throwable e) {
             throw new IllegalStateException("批次转换失败", e);
-        }finally{
-            if(bufferedReader!=null){
+        } finally {
+            if (bufferedReader != null) {
                 try {
                     bufferedReader.close();
                 } catch (IOException e) {
@@ -453,71 +444,70 @@ public class IndexServiceImpl implements IndexService {
         }
     }
 
-	private Long createOrderIndexes() {
-		logger.info("正在创建销售单索引...");
-		List<Order> orders = orderDao.findAll();
-		logger.info("发现数据:" + orders.size() + "条");
-		return createIndexesWithObjects(orders.toArray());
-	}
-
-	private Long createOrderInvoiceIndexes() {
-		logger.info("正在创建销售发货单索引...");
-		List<OrderInvoice> orderInvoices = orderInvoiceDao.findAll();
-		logger.info("发现数据:" + orderInvoices.size() + "条");
-		return createIndexesWithObjects(orderInvoices.toArray());
-	}
-
-	private Long createPurchaseIndexes() {
-		logger.info("正在创建采购单索引...");
-		List<Purchase> purchases = purchaseDao.findAll();
-		logger.info("发现数据:" + purchases.size() + "条");
-		return createIndexesWithObjects(purchases.toArray());
-	}
-
-	private Long createPurchaseInvoiceIndexes() {
-		logger.info("正在创建采购发货单索引...");
-		List<PurchaseInvoice> purchaseInvoices = purchaseInvoiceDao.findAll();
-		logger.info("发现数据:" + purchaseInvoices.size() + "条");
-		return createIndexesWithObjects(purchaseInvoices.toArray());
-	}
-
-	/**
-	 * 利用对象数组创建索引
-	 *
-	 * @param objects
-	 *            对象数组,可为Kind、Brand、Order、
-	 *            OrderInvoice、Purchase、
-	 *            PurchaseInvoice
-	 * @return 对象数组的数量
-	 */
-	private Long createIndexesWithObjects(Object[] objects) {
-		if (objects == null || objects.length < 1)
-			return 0L;
-
-		long count = 0;
-		try {
-			for (Object object : objects) {
-				Document document = ObjectToDocumentUtils.toDocument(object);
-				if (document != null) {
-					indexWriter.addDocument(document);
-					count++;
-				}
-			}
-			indexWriter.commit();
-		} catch (IOException e) {
-			logger.error("", e);
-		}
-		return count;
-	}
+    private Long createOrderIndexes() {
+        logger.info("正在创建销售单索引...");
+        List<Order> orders = orderDao.findAll();
+        logger.info("发现数据:" + orders.size() + "条");
+        return createIndexesWithObjects(orders.toArray());
+    }
+
+    private Long createOrderInvoiceIndexes() {
+        logger.info("正在创建销售发货单索引...");
+        List<OrderInvoice> orderInvoices = orderInvoiceDao.findAll();
+        logger.info("发现数据:" + orderInvoices.size() + "条");
+        return createIndexesWithObjects(orderInvoices.toArray());
+    }
+
+    private Long createPurchaseIndexes() {
+        logger.info("正在创建采购单索引...");
+        List<Purchase> purchases = purchaseDao.findAll();
+        logger.info("发现数据:" + purchases.size() + "条");
+        return createIndexesWithObjects(purchases.toArray());
+    }
+
+    private Long createPurchaseInvoiceIndexes() {
+        logger.info("正在创建采购发货单索引...");
+        List<PurchaseInvoice> purchaseInvoices = purchaseInvoiceDao.findAll();
+        logger.info("发现数据:" + purchaseInvoices.size() + "条");
+        return createIndexesWithObjects(purchaseInvoices.toArray());
+    }
+
+    /**
+     * 利用对象数组创建索引
+     *
+     * @param objects 对象数组,可为Kind、Brand、Order、
+     *                OrderInvoice、Purchase、
+     *                PurchaseInvoice
+     * @return 对象数组的数量
+     */
+    private Long createIndexesWithObjects(Object[] objects) {
+        if (objects == null || objects.length < 1)
+            return 0L;
+
+        long count = 0;
+        try {
+            for (Object object : objects) {
+                Document document = ObjectToDocumentUtils.toDocument(object);
+                if (document != null) {
+                    indexWriter.addDocument(document);
+                    count++;
+                }
+            }
+            indexWriter.commit();
+        } catch (IOException e) {
+            logger.error("", e);
+        }
+        return count;
+    }
 
     @Override
     public long multiDownloadComponent(Integer threads, Integer startFileIndex, Integer endFileIndex, DownloadHelper.ValidateResult validateResult) {
-        return multiDownloadData(COMPONENT_TABLE_NAME,threads,startFileIndex,endFileIndex, validateResult);
+        return multiDownloadData(COMPONENT_TABLE_NAME, threads, startFileIndex, endFileIndex, validateResult);
     }
 
     @Override
     public long multiDownloadGoods(Integer threads, Integer startFileIndex, Integer endFileIndex, DownloadHelper.ValidateResult validateResult) {
-        return multiDownloadData(GOODS_TABLE_NAME,threads,startFileIndex,endFileIndex, validateResult);
+        return multiDownloadData(GOODS_TABLE_NAME, threads, startFileIndex, endFileIndex, validateResult);
     }
 
     /**
@@ -537,11 +527,11 @@ public class IndexServiceImpl implements IndexService {
         }
 
         if (tableName.equals(COMPONENT_TABLE_NAME)) {
-            DownloadHelper<Component> downloadHelper = new DownloadHelper<>(threads, startFileIndex, endFileIndex, tableName, "id",componentDao, new DownloadService<Component>(), validateResult);
+            DownloadHelper<Component> downloadHelper = new DownloadHelper<>(threads, startFileIndex, endFileIndex, tableName, "id", componentDao, new DownloadService<Component>(), validateResult);
             return downloadHelper.getResult();
 
         } else if (tableName.equals(GOODS_TABLE_NAME)) {
-            DownloadHelper<TradeGoods> downloadHelper = new DownloadHelper<>(threads, startFileIndex, endFileIndex, tableName, "id",tradeGoodsDao, new DownloadService<TradeGoods>(){
+            DownloadHelper<TradeGoods> downloadHelper = new DownloadHelper<>(threads, startFileIndex, endFileIndex, tableName, "id", tradeGoodsDao, new DownloadService<TradeGoods>() {
                 @Override
                 protected void println(PrintWriter printWriter, TradeGoods element) {
                     Goods goods = goodsDao.findByTradeGoods(element);
@@ -554,141 +544,196 @@ public class IndexServiceImpl implements IndexService {
         }
     }
 
-	@Override
-	public Object save(Object obj) {
-		if (obj != null) {
-			String tableName = SearchUtils.getTableName(obj.getClass());
-			Document document = ObjectToDocumentUtils.toDocument(obj);
-			if (document != null) {
-				try {
-					indexWriter = indexWriterManager.get(tableName);
-					indexWriter.addDocument(document);
-					indexSearcherManager.flushCache(tableName, indexWriter, null);
-					return obj;
-				} catch (IOException | InterruptedException e) {
-					logger.error("", e);
-				} finally {
-					indexWriterManager.release(tableName);
-				}
-			} else {
-				logger.info("对象转为Document时为null:" + obj);
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public Object update(Object obj) {
-		if (obj != null) {
-			String tableName = SearchUtils.getTableName(obj.getClass());
-			Document document = ObjectToDocumentUtils.toDocument(obj);
-			if (document != null) {
-				try {
-					indexWriter = indexWriterManager.get(tableName);
-					if (obj instanceof Kind) {
-						indexWriter.updateDocument(
-								new Term(SearchConstants.KIND_ID_FIELD, String.valueOf(((Kind) obj).getId())),
-								document);
-					} else if (obj instanceof Brand) {
-						indexWriter.updateDocument(new Term(SearchConstants.BRAND_ID_FIELD,
-								String.valueOf(((Brand) obj).getId())), document);
-					} else if (obj instanceof Component) {
-						indexWriter.updateDocument(new Term(SearchConstants.COMPONENT_ID_FIELD,
-								String.valueOf(((Component) obj).getId())), document);
-					} else if (obj instanceof Order) {
-						indexWriter.updateDocument(new Term(SearchConstants.ORDER_ID_FIELD,
-								String.valueOf(((Order) obj).getId())), document);
-					} else if (obj instanceof OrderInvoice) {
-						indexWriter.updateDocument(new Term(SearchConstants.ORDER_INVOICE_ID_FIELD,
-								String.valueOf(((OrderInvoice) obj).getId())), document);
-					} else if (obj instanceof Purchase) {
-						indexWriter.updateDocument(new Term(SearchConstants.PURCHASE_ID_FIELD,
-								String.valueOf(((Purchase) obj).getId())), document);
-					} else if (obj instanceof PurchaseInvoice) {
-						indexWriter.updateDocument(new Term(SearchConstants.PURCHASE_INVOICE_ID_FIELD,
-								String.valueOf(((PurchaseInvoice) obj).getId())), document);
-					} else {
-						throw new IllegalStateException("Message parsing failed!");
-					}
-					indexSearcherManager.flushCache(tableName, indexWriter, null);
-					return obj;
-				} catch (IOException | InterruptedException e) {
-					logger.error("", e);
-				} finally {
-					indexWriterManager.release(tableName);
-				}
-			} else {
-				logger.info("对象转为Document时为null:" + obj);
-			}
-		}
-		return null;
-	}
-
-	@Override
-	public Object delete(Object obj) {
-		if (obj != null) {
-			String tableName = SearchUtils.getTableName(obj.getClass());
-			try {
-				indexWriter = indexWriterManager.get(tableName);
-				if (obj instanceof Kind) {
-					indexWriter.deleteDocuments(
-							new Term(SearchConstants.KIND_ID_FIELD, String.valueOf(((Kind) obj).getId())));
-				} else if (obj instanceof Brand) {
-					indexWriter.deleteDocuments(
-							new Term(SearchConstants.BRAND_ID_FIELD, String.valueOf(((Brand) obj).getId())));
-				} else if (obj instanceof Component) {
-					indexWriter.deleteDocuments(new Term(SearchConstants.COMPONENT_ID_FIELD,
-							String.valueOf(((Component) obj).getId())));
-				} else if (obj instanceof Goods) {
-					indexWriter.deleteDocuments(toTerm((Goods) obj));
-				} else if (obj instanceof Order) {
-					indexWriter.deleteDocuments(
-							new Term(SearchConstants.ORDER_ID_FIELD, String.valueOf(((Order) obj).getId())));
-				} else if (obj instanceof OrderInvoice) {
-					indexWriter.deleteDocuments(new Term(SearchConstants.ORDER_INVOICE_ID_FIELD,
-							String.valueOf(((OrderInvoice) obj).getId())));
-				} else if (obj instanceof Purchase) {
-					indexWriter.deleteDocuments(new Term(SearchConstants.PURCHASE_ID_FIELD,
-							String.valueOf(((Purchase) obj).getId())));
-				} else if (obj instanceof PurchaseInvoice) {
-					indexWriter.deleteDocuments(new Term(SearchConstants.PURCHASE_INVOICE_ID_FIELD,
-							String.valueOf(((PurchaseInvoice) obj).getId())));
-				} else {
-					throw new IllegalStateException("Message parsing failed!");
-				}
-				indexSearcherManager.flushCache(tableName, indexWriter, null);
-				return obj;
-			} catch (IOException | InterruptedException e) {
-				logger.error("", e);
-			} finally {
-				indexWriterManager.release(tableName);
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * 根据goods构造Term
-	 *
-	 * @param goods
-	 * @return
-	 */
-	private Term toTerm(Goods goods) {
+    @Override
+    public Object save(Object obj) {
+        if (obj != null) {
+            String tableName = SearchUtils.getTableName(obj.getClass());
+            Document document = ObjectToDocumentUtils.toDocument(obj);
+            if (document != null) {
+                try {
+                    indexWriter = indexWriterManager.get(tableName);
+                    indexWriter.addDocument(document);
+                    indexSearcherManager.flushCache(tableName, indexWriter, null);
+                    return obj;
+                } catch (IOException | InterruptedException e) {
+                    logger.error("", e);
+                } finally {
+                    indexWriterManager.release(tableName);
+                }
+            } else {
+                logger.info("对象转为Document时为null:" + obj);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Object update(Object obj) {
+        if (obj != null) {
+            String tableName = SearchUtils.getTableName(obj.getClass());
+            Document document = ObjectToDocumentUtils.toDocument(obj);
+            if (document != null) {
+                try {
+                    indexWriter = indexWriterManager.get(tableName);
+                    if (obj instanceof Kind) {
+                        indexWriter.updateDocument(
+                                new Term(SearchConstants.KIND_ID_FIELD, String.valueOf(((Kind) obj).getId())),
+                                document);
+                    } else if (obj instanceof Brand) {
+                        Brand brand = (Brand) obj;
+                        indexWriter.updateDocument(new Term(SearchConstants.BRAND_ID_FIELD,
+                                String.valueOf(brand.getId())), document);
+                        // 更新关联批次
+                        updateGoodsFields(new Term(SearchConstants.GOODS_BR_ID_FIELD, brand.getId().toString()), brand, null);
+                    } else if (obj instanceof Component) {
+                        indexWriter.updateDocument(new Term(SearchConstants.COMPONENT_ID_FIELD,
+                                String.valueOf(((Component) obj).getId())), document);
+                    } else if (obj instanceof Order) {
+                        indexWriter.updateDocument(new Term(SearchConstants.ORDER_ID_FIELD,
+                                String.valueOf(((Order) obj).getId())), document);
+                    } else if (obj instanceof OrderInvoice) {
+                        indexWriter.updateDocument(new Term(SearchConstants.ORDER_INVOICE_ID_FIELD,
+                                String.valueOf(((OrderInvoice) obj).getId())), document);
+                    } else if (obj instanceof Purchase) {
+                        indexWriter.updateDocument(new Term(SearchConstants.PURCHASE_ID_FIELD,
+                                String.valueOf(((Purchase) obj).getId())), document);
+                    } else if (obj instanceof PurchaseInvoice) {
+                        indexWriter.updateDocument(new Term(SearchConstants.PURCHASE_INVOICE_ID_FIELD,
+                                String.valueOf(((PurchaseInvoice) obj).getId())), document);
+                    } else {
+                        throw new IllegalStateException("Message parsing failed!");
+                    }
+                    indexSearcherManager.flushCache(tableName, indexWriter, null);
+                    return obj;
+                } catch (IOException | InterruptedException e) {
+                    logger.error("", e);
+                } finally {
+                    indexWriterManager.release(tableName);
+                }
+            } else {
+                logger.info("对象转为Document时为null:" + obj);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 更新关联的批次
+     *
+     * @param term 指定的批次
+     * @param brand 新的品牌
+     * @param kind 新的类目
+     * @throws IOException
+     */
+    private void updateGoodsFields(Term term, Brand brand, Kind kind) throws IOException {
+        if (brand == null && kind == null) {
+            return;
+        }
+        String tableName = SearchConstants.GOODS_TABLE_NAME;
+        Query query = new TermQuery(term);
+        int page = 1;
+        int size = 1000;
+        SPage<Document> documents = SearchUtils.getDocuments(tableName, query, page, size);
+        logger.info("更新关联批次索引:total=" + documents.getTotalElement());
+        int totalPage = documents.getTotalPage();
+        IndexWriter writer = null;
+        try {
+            writer = indexWriterManager.get(tableName);
+            String idField = SearchUtils.getIdField(tableName);
+            while (true) {
+                for (Document document : documents.getContent()) {
+                    Goods goods = DocumentToObjectUtils.toGoods(document);
+                    if (brand != null) {
+                        goods.getComponent().setBrand(brand);
+                    }
+                    if (kind != null) {
+                        goods.getComponent().setKind(kind);
+                    }
+                    writer.updateDocument(new Term(idField, document.get(idField)), ObjectToDocumentUtils.toDocument(goods));
+                }
+                logger.info("更新关联批次索引:count=" + tableName + ", count=" + (size * (page - 1) + documents.getContent().size()));
+                writer.commit();
+                page++;
+                if (page > totalPage) {
+                    break;
+                }
+                documents = SearchUtils.getDocuments(tableName, query, page, size);
+            }
+        } catch (InterruptedException e) {
+            logger.error("", e);
+        } finally {
+            if (writer != null) {
+                indexSearcherManager.flushCache(tableName, writer, null);
+                indexWriterManager.release(tableName);
+            }
+        }
+    }
+
+    @Override
+    public Object delete(Object obj) {
+        if (obj != null) {
+            String tableName = SearchUtils.getTableName(obj.getClass());
+            try {
+                indexWriter = indexWriterManager.get(tableName);
+                if (obj instanceof Kind) {
+                    indexWriter.deleteDocuments(
+                            new Term(SearchConstants.KIND_ID_FIELD, String.valueOf(((Kind) obj).getId())));
+                } else if (obj instanceof Brand) {
+                    indexWriter.deleteDocuments(
+                            new Term(SearchConstants.BRAND_ID_FIELD, String.valueOf(((Brand) obj).getId())));
+                } else if (obj instanceof Component) {
+                    indexWriter.deleteDocuments(new Term(SearchConstants.COMPONENT_ID_FIELD,
+                            String.valueOf(((Component) obj).getId())));
+                } else if (obj instanceof Goods) {
+                    indexWriter.deleteDocuments(toTerm((Goods) obj));
+                } else if (obj instanceof Order) {
+                    indexWriter.deleteDocuments(
+                            new Term(SearchConstants.ORDER_ID_FIELD, String.valueOf(((Order) obj).getId())));
+                } else if (obj instanceof OrderInvoice) {
+                    indexWriter.deleteDocuments(new Term(SearchConstants.ORDER_INVOICE_ID_FIELD,
+                            String.valueOf(((OrderInvoice) obj).getId())));
+                } else if (obj instanceof Purchase) {
+                    indexWriter.deleteDocuments(new Term(SearchConstants.PURCHASE_ID_FIELD,
+                            String.valueOf(((Purchase) obj).getId())));
+                } else if (obj instanceof PurchaseInvoice) {
+                    indexWriter.deleteDocuments(new Term(SearchConstants.PURCHASE_INVOICE_ID_FIELD,
+                            String.valueOf(((PurchaseInvoice) obj).getId())));
+                } else {
+                    throw new IllegalStateException("Message parsing failed!");
+                }
+                indexSearcherManager.flushCache(tableName, indexWriter, null);
+                return obj;
+            } catch (IOException | InterruptedException e) {
+                logger.error("", e);
+            } finally {
+                indexWriterManager.release(tableName);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 根据goods构造Term
+     *
+     * @param goods
+     * @return
+     */
+    private Term toTerm(Goods goods) {
         if (goods.getComponent() != null) {
             return new Term(SearchConstants.GOODS_CMP_ID_FIELD, String.valueOf(goods.getComponent().getId()));
         } else if (goods.getTradeGoods() != null) {
             return new Term(SearchConstants.GOODS_GO_ID_FIELD, String.valueOf(goods.getTradeGoods().getId()));
         }
-		return null;
-	}
-
-	@Override
-	public List<Object> maintainIndexes(@NotEmpty("parsedQueueMessage") ParsedQueueMessage parsedQueueMessage) {
-		Object object = parsedQueueMessage.getObject();
-		if (object == null) {
-			return null;
-		}
-		List<Object> maintainedObjects = new ArrayList<>();
+        return null;
+    }
+
+    @Override
+    public List<Object> maintainIndexes(@NotEmpty("parsedQueueMessage") ParsedQueueMessage parsedQueueMessage) {
+        Object object = parsedQueueMessage.getObject();
+        if (object == null) {
+            return null;
+        }
+        List<Object> maintainedObjects = new ArrayList<>();
         // 新增、更新索引
         if (parsedQueueMessage.isInsert() || parsedQueueMessage.isUpdate()) {
             if (object instanceof Goods) {
@@ -726,7 +771,7 @@ public class IndexServiceImpl implements IndexService {
                         }
                     } catch (DataNotFoundException e) {
                         // 删除操作时,器件可能已经不存在,此时是正常情况,不必抛异常
-                        logger.warn("器件已删除,不必重新写入相关批次和器件" ,e);
+                        logger.warn("器件已删除,不必重新写入相关批次和器件", e);
                     }
                 }
             } else {
@@ -738,38 +783,38 @@ public class IndexServiceImpl implements IndexService {
         } else {
             throw new IllegalStateException("message parsing failed!");
         }
-		return maintainedObjects;
-	}
-
-	@Override
-	public List<Object> maintainIndexes(@NotEmpty("tableName") String tableName, @NotEmpty("dataId") Long dataId, @NotEmpty("methodType") String methodType, String data) {
-		ParsedQueueMessage parsedQueueMessage = queueMessageParser.parse(tableName, dataId, methodType, data);
-		return maintainIndexes(parsedQueueMessage);
-	}
-
-	@Override
-	public Map<String, List<Object>> updateIndexByNewWords(List<String> newWords) throws IOException {
-		Map<String, List<Object>> updatedObjects = new HashMap<>();
-		// 类目
-		updatedObjects.put(SearchConstants.KIND_TABLE_NAME, updateIndexByNewWords(newWords,
-				SearchConstants.KIND_TABLE_NAME, SearchConstants.KIND_ID_FIELD,
-				SearchConstants.KIND_NAMECN_FIELD));
-		// 品牌
-		updatedObjects.put(SearchConstants.BRAND_TABLE_NAME, updateIndexByNewWords(newWords,
-				SearchConstants.BRAND_TABLE_NAME, SearchConstants.BRAND_ID_FIELD,
-				SearchConstants.BRAND_NAMECN_FIELD, SearchConstants.BRAND_NAMEEN_FIELD));
-		// 器件
-		updatedObjects.put(SearchConstants.COMPONENT_TABLE_NAME, updateIndexByNewWords(newWords,
-				SearchConstants.COMPONENT_TABLE_NAME, SearchConstants.COMPONENT_ID_FIELD,
-				SearchConstants.COMPONENT_CODE_FIELD, SearchConstants.COMPONENT_KI_NAME_FIELD,
-				SearchConstants.COMPONENT_BR_NAMECN_FIELD, SearchConstants.COMPONENT_BR_NAMEEN_FIELD));
-		// 批次
-		updatedObjects.put(SearchConstants.GOODS_TABLE_NAME, updateIndexByNewWords(newWords,
-				SearchConstants.GOODS_TABLE_NAME, SearchConstants.GOODS_CMP_ID_FIELD,
-				SearchConstants.GOODS_CMP_CODE_FIELD, SearchConstants.GOODS_KI_NAME_CN_FIELD,
-				SearchConstants.GOODS_BR_NAME_CN_UNTOKENIZED_FIELD, SearchConstants.GOODS_BR_NAME_EN_UNTOKENIZED_FIELD));
-		return updatedObjects;
-	}
+        return maintainedObjects;
+    }
+
+    @Override
+    public List<Object> maintainIndexes(@NotEmpty("tableName") String tableName, @NotEmpty("dataId") Long dataId, @NotEmpty("methodType") String methodType, String data) {
+        ParsedQueueMessage parsedQueueMessage = queueMessageParser.parse(tableName, dataId, methodType, data);
+        return maintainIndexes(parsedQueueMessage);
+    }
+
+    @Override
+    public Map<String, List<Object>> updateIndexByNewWords(List<String> newWords) throws IOException {
+        Map<String, List<Object>> updatedObjects = new HashMap<>();
+        // 类目
+        updatedObjects.put(SearchConstants.KIND_TABLE_NAME, updateIndexByNewWords(newWords,
+                SearchConstants.KIND_TABLE_NAME, SearchConstants.KIND_ID_FIELD,
+                SearchConstants.KIND_NAMECN_FIELD));
+        // 品牌
+        updatedObjects.put(SearchConstants.BRAND_TABLE_NAME, updateIndexByNewWords(newWords,
+                SearchConstants.BRAND_TABLE_NAME, SearchConstants.BRAND_ID_FIELD,
+                SearchConstants.BRAND_NAMECN_FIELD, SearchConstants.BRAND_NAMEEN_FIELD));
+        // 器件
+        updatedObjects.put(SearchConstants.COMPONENT_TABLE_NAME, updateIndexByNewWords(newWords,
+                SearchConstants.COMPONENT_TABLE_NAME, SearchConstants.COMPONENT_ID_FIELD,
+                SearchConstants.COMPONENT_CODE_FIELD, SearchConstants.COMPONENT_KI_NAME_FIELD,
+                SearchConstants.COMPONENT_BR_NAMECN_FIELD, SearchConstants.COMPONENT_BR_NAMEEN_FIELD));
+        // 批次
+        updatedObjects.put(SearchConstants.GOODS_TABLE_NAME, updateIndexByNewWords(newWords,
+                SearchConstants.GOODS_TABLE_NAME, SearchConstants.GOODS_CMP_ID_FIELD,
+                SearchConstants.GOODS_CMP_CODE_FIELD, SearchConstants.GOODS_KI_NAME_CN_FIELD,
+                SearchConstants.GOODS_BR_NAME_CN_UNTOKENIZED_FIELD, SearchConstants.GOODS_BR_NAME_EN_UNTOKENIZED_FIELD));
+        return updatedObjects;
+    }
 
     /**
      * 根据(录入的词典)新词更新指定表的索引

+ 113 - 111
mall-search/src/main/java/com/uas/search/util/DocumentToObjectUtils.java

@@ -172,128 +172,130 @@ public class DocumentToObjectUtils {
 	 * @param document
 	 * @return
 	 */
-	public static Goods toGoods(Document document) {
-		if (document == null) {
-			return null;
-		}
-		Goods goods = new Goods();
-		TradeGoods tradeGoods = new TradeGoods();
+    public static Goods toGoods(Document document) {
+        if (document == null) {
+            return null;
+        }
+        Goods goods = new Goods();
         String goId = document.get(SearchConstants.GOODS_GO_ID_FIELD);
         if (!StringUtils.isEmpty(goId) && !goId.equals(ObjectToDocumentUtils.NULL_VALUE)) {
-			tradeGoods.setId(Long.valueOf(goId));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_RESERVE_FIELD))) {
-			tradeGoods.setReserve(Double.valueOf(document.get(SearchConstants.GOODS_GO_RESERVE_FIELD)));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_STATUS_FIELD))) {
-			tradeGoods.setStatus(Long.valueOf(document.get(SearchConstants.GOODS_GO_STATUS_FIELD)));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_MINPRICERMB_FIELD))) {
-			tradeGoods.setMinPriceRMB(Double.valueOf(document.get(SearchConstants.GOODS_GO_MINPRICERMB_FIELD)));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD))) {
-			tradeGoods.setMinPriceUSD(Double.valueOf(document.get(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD)));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CRNAME_FIELD))) {
-			tradeGoods.setCrName(document.get(SearchConstants.GOODS_CRNAME_FIELD));
-		}
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_VISIT_COUNT_FIELD))) {
-            tradeGoods.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_GO_VISIT_COUNT_FIELD)));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_UPDATE_DATE_FIELD))) {
-            tradeGoods.setUpdateDate(new Date(Long.valueOf(document.get(SearchConstants.GOODS_GO_UPDATE_DATE_FIELD))));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_MINDELIVERY_FIELD))) {
-            tradeGoods.setMinDelivery(Long.valueOf(document.get(SearchConstants.GOODS_GO_MINDELIVERY_FIELD)));
-        }
-		goods.setTradeGoods(tradeGoods);
+            TradeGoods tradeGoods = new TradeGoods();
+            tradeGoods.setId(Long.valueOf(goId));
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_RESERVE_FIELD))) {
+                tradeGoods.setReserve(Double.valueOf(document.get(SearchConstants.GOODS_GO_RESERVE_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_STATUS_FIELD))) {
+                tradeGoods.setStatus(Long.valueOf(document.get(SearchConstants.GOODS_GO_STATUS_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_MINPRICERMB_FIELD))) {
+                tradeGoods.setMinPriceRMB(Double.valueOf(document.get(SearchConstants.GOODS_GO_MINPRICERMB_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD))) {
+                tradeGoods.setMinPriceUSD(Double.valueOf(document.get(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CRNAME_FIELD))) {
+                tradeGoods.setCrName(document.get(SearchConstants.GOODS_CRNAME_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_VISIT_COUNT_FIELD))) {
+                tradeGoods.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_GO_VISIT_COUNT_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_UPDATE_DATE_FIELD))) {
+                tradeGoods.setUpdateDate(new Date(Long.valueOf(document.get(SearchConstants.GOODS_GO_UPDATE_DATE_FIELD))));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_GO_MINDELIVERY_FIELD))) {
+                tradeGoods.setMinDelivery(Long.valueOf(document.get(SearchConstants.GOODS_GO_MINDELIVERY_FIELD)));
+            }
+            goods.setTradeGoods(tradeGoods);
 
-		Store store = new Store();
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_ST_UUID_FIELD))) {
-			store.setUuid(document.get(SearchConstants.GOODS_ST_UUID_FIELD));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_ST_TYPE_FIELD))) {
-			store.setType(document.get(SearchConstants.GOODS_ST_TYPE_FIELD));
-		}
-		goods.setStore(store);
 
-		Component component = new Component();
+            Store store = new Store();
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_ST_UUID_FIELD))) {
+                store.setUuid(document.get(SearchConstants.GOODS_ST_UUID_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_ST_TYPE_FIELD))) {
+                store.setType(document.get(SearchConstants.GOODS_ST_TYPE_FIELD));
+            }
+            goods.setStore(store);
+        }
+
         String cmpId = document.get(SearchConstants.GOODS_CMP_ID_FIELD);
         if (!StringUtils.isEmpty(cmpId) && !cmpId.equals(ObjectToDocumentUtils.NULL_VALUE)) {
+            Component component = new Component();
             component.setId(Long.valueOf(cmpId));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_CODE_FIELD))) {
-            component.setCode(document.get(SearchConstants.GOODS_CMP_CODE_FIELD));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_DESCRIPTION_FIELD))) {
-            component.setDescription(document.get(SearchConstants.GOODS_CMP_DESCRIPTION_FIELD));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_VISIT_COUNT_FIELD))) {
-            component.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_CMP_VISIT_COUNT_FIELD)));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_SEARCH_COUNT_FIELD))) {
-            component.setSearchCount(Long.valueOf(document.get(SearchConstants.GOODS_CMP_SEARCH_COUNT_FIELD)));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_WEIGHT_FIELD))) {
-            component.setWeight(Double.valueOf(document.get(SearchConstants.GOODS_CMP_WEIGHT_FIELD)));
-        }
 
-		Kind kind = new Kind();
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_ID_FIELD))) {
-			kind.setId(Long.valueOf(document.get(SearchConstants.GOODS_KI_ID_FIELD)));
-		}
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_NAME_CN_FIELD))) {
-		    kind.setNameCn(document.get(SearchConstants.GOODS_KI_NAME_CN_FIELD));
-        }
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_LEVEL_FIELD))) {
-			kind.setLevel(Short.valueOf(document.get(SearchConstants.GOODS_KI_LEVEL_FIELD)));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_ISLEAF_FIELD))) {
-			kind.setIsLeaf(Short.valueOf(document.get(SearchConstants.GOODS_KI_ISLEAF_FIELD)));
-		}
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_VISIT_COUNT_FIELD))) {
-            kind.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_KI_VISIT_COUNT_FIELD)));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_SEARCH_COUNT_FIELD))) {
-            kind.setSearchCount(Long.valueOf(document.get(SearchConstants.GOODS_KI_SEARCH_COUNT_FIELD)));
-        }
-		component.setKind(kind);
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_CODE_FIELD))) {
+                component.setCode(document.get(SearchConstants.GOODS_CMP_CODE_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_DESCRIPTION_FIELD))) {
+                component.setDescription(document.get(SearchConstants.GOODS_CMP_DESCRIPTION_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_VISIT_COUNT_FIELD))) {
+                component.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_CMP_VISIT_COUNT_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_SEARCH_COUNT_FIELD))) {
+                component.setSearchCount(Long.valueOf(document.get(SearchConstants.GOODS_CMP_SEARCH_COUNT_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_CMP_WEIGHT_FIELD))) {
+                component.setWeight(Double.valueOf(document.get(SearchConstants.GOODS_CMP_WEIGHT_FIELD)));
+            }
 
-		Brand brand = new Brand();
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_ID_FIELD))) {
-			brand.setId(Long.valueOf(document.get(SearchConstants.GOODS_BR_ID_FIELD)));
-		}
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_NAME_CN_FIELD))) {
-		    brand.setNameCn(document.get(SearchConstants.GOODS_BR_NAME_CN_FIELD));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_UUID_FIELD))) {
-		    brand.setUuid(document.get(SearchConstants.GOODS_BR_UUID_FIELD));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_NAME_EN_FIELD))) {
-            brand.setNameEn(document.get(SearchConstants.GOODS_BR_NAME_EN_FIELD));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_VISIT_COUNT_FIELD))) {
-            brand.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_BR_VISIT_COUNT_FIELD)));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_SEARCH_COUNT_FIELD))) {
-            brand.setSearchCount(Long.valueOf(document.get(SearchConstants.GOODS_BR_SEARCH_COUNT_FIELD)));
-        }
-        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_WEIGHT_FIELD))) {
-            brand.setWeight(Double.valueOf(document.get(SearchConstants.GOODS_BR_WEIGHT_FIELD)));
+            Kind kind = new Kind();
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_ID_FIELD))) {
+                kind.setId(Long.valueOf(document.get(SearchConstants.GOODS_KI_ID_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_NAME_CN_FIELD))) {
+                kind.setNameCn(document.get(SearchConstants.GOODS_KI_NAME_CN_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_LEVEL_FIELD))) {
+                kind.setLevel(Short.valueOf(document.get(SearchConstants.GOODS_KI_LEVEL_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_ISLEAF_FIELD))) {
+                kind.setIsLeaf(Short.valueOf(document.get(SearchConstants.GOODS_KI_ISLEAF_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_VISIT_COUNT_FIELD))) {
+                kind.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_KI_VISIT_COUNT_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_KI_SEARCH_COUNT_FIELD))) {
+                kind.setSearchCount(Long.valueOf(document.get(SearchConstants.GOODS_KI_SEARCH_COUNT_FIELD)));
+            }
+            component.setKind(kind);
+
+            Brand brand = new Brand();
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_ID_FIELD))) {
+                brand.setId(Long.valueOf(document.get(SearchConstants.GOODS_BR_ID_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_NAME_CN_FIELD))) {
+                brand.setNameCn(document.get(SearchConstants.GOODS_BR_NAME_CN_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_UUID_FIELD))) {
+                brand.setUuid(document.get(SearchConstants.GOODS_BR_UUID_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_NAME_EN_FIELD))) {
+                brand.setNameEn(document.get(SearchConstants.GOODS_BR_NAME_EN_FIELD));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_VISIT_COUNT_FIELD))) {
+                brand.setVisitCount(Long.valueOf(document.get(SearchConstants.GOODS_BR_VISIT_COUNT_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_SEARCH_COUNT_FIELD))) {
+                brand.setSearchCount(Long.valueOf(document.get(SearchConstants.GOODS_BR_SEARCH_COUNT_FIELD)));
+            }
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_BR_WEIGHT_FIELD))) {
+                brand.setWeight(Double.valueOf(document.get(SearchConstants.GOODS_BR_WEIGHT_FIELD)));
+            }
+            component.setBrand(brand);
+            goods.setComponent(component);
         }
-		component.setBrand(brand);
-		goods.setComponent(component);
 
-		Products products = new Products();
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_PR_ID_FIELD))) {
-			products.setId(Long.valueOf(document.get(SearchConstants.GOODS_PR_ID_FIELD)));
-		}
-		if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_PR_PCMPCODE_FIELD))) {
-			products.setPcmpCode(document.get(SearchConstants.GOODS_PR_PCMPCODE_FIELD));
-		}
-		goods.setProducts(products);
-		return goods;
-	}
+        if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_PR_ID_FIELD))) {
+            Products products = new Products();
+            products.setId(Long.valueOf(document.get(SearchConstants.GOODS_PR_ID_FIELD)));
+            if (!StringUtils.isEmpty(document.get(SearchConstants.GOODS_PR_PCMPCODE_FIELD))) {
+                products.setPcmpCode(document.get(SearchConstants.GOODS_PR_PCMPCODE_FIELD));
+            }
+            goods.setProducts(products);
+        }
+        return goods;
+    }
 
 	/**
 	 * 将Document转换为销售单对象

+ 11 - 5
mall-search/src/main/java/com/uas/search/util/ObjectToDocumentUtils.java

@@ -238,14 +238,15 @@ public class ObjectToDocumentUtils {
 	 */
 	public static Document toDocument(Goods goods) {
 		if (goods == null ||
-				(goods.getComponent() != null &&
-						(StringUtils.isEmpty(goods.getComponent().getId()) ||
+                (goods.getTradeGoods() != null && goods.getTradeGoods().getId() == null) ||
+				(goods.getComponent() != null && (goods.getComponent().getId() == null ||
 								StringUtils.isEmpty(goods.getComponent().getCode()) ||
 								goods.getComponent().getKind() == null ||
 								goods.getComponent().getBrand() == null))) {
 			return null;
 		}
 
+		String primaryKey = "";
 		Document document = new Document();
 		if(goods.getTradeGoods() != null){
 			TradeGoods tradeGoods = goods.getTradeGoods();
@@ -284,9 +285,11 @@ public class ObjectToDocumentUtils {
                 document.add(new DoubleDocValuesField(SearchConstants.GOODS_GO_MINDELIVERY_FIELD, tradeGoods.getMinDelivery()));
                 document.add(new LongField(SearchConstants.GOODS_GO_MINDELIVERY_FIELD, tradeGoods.getMinDelivery(), Store.YES));
             }
+            primaryKey += tradeGoods.getId();
 		} else {
             // 批次 id 为 null 时,存默认值,以便于后期搜索时做空值过滤
             document.add(new StringField(SearchConstants.GOODS_GO_ID_FIELD, NULL_VALUE, Store.YES));
+            primaryKey += NULL_VALUE;
         }
 
 		if (goods.getStore() != null) {
@@ -330,12 +333,12 @@ public class ObjectToDocumentUtils {
 				document.add(new BinaryDocValuesField(SearchConstants.GOODS_KI_NAME_CN_UNTOKENIZED_FIELD, new BytesRef( kind.getNameCn())));
 			}
 			if (kind.getLevel() != null) {
-				document.add(new NumericDocValuesField(SearchConstants.GOODS_KI_LEVEL_FIELD, kind.getIsLeaf()));
-				document.add(new LongField(SearchConstants.GOODS_KI_LEVEL_FIELD, kind.getIsLeaf(), Store.YES));
+				document.add(new NumericDocValuesField(SearchConstants.GOODS_KI_LEVEL_FIELD, kind.getLevel()));
+				document.add(new LongField(SearchConstants.GOODS_KI_LEVEL_FIELD, kind.getLevel(), Store.YES));
 			}
 			if (kind.getIsLeaf() != null) {
 				document.add(
-						new StringField(SearchConstants.GOODS_KI_ISLEAF_FIELD, String.valueOf(kind.getLevel()), Store.YES));
+						new StringField(SearchConstants.GOODS_KI_ISLEAF_FIELD, String.valueOf(kind.getIsLeaf()), Store.YES));
 			}
 			if (kind.getVisitCount() != null) {
 				document.add(new DoubleDocValuesField(SearchConstants.GOODS_KI_VISIT_COUNT_FIELD, kind.getVisitCount()));
@@ -375,9 +378,11 @@ public class ObjectToDocumentUtils {
 				document.add(new DoubleDocValuesField(SearchConstants.GOODS_BR_WEIGHT_FIELD, brand.getWeight()));
 				document.add(new DoubleField(SearchConstants.GOODS_BR_WEIGHT_FIELD, brand.getWeight(), Store.YES));
 			}
+            primaryKey += "_" + component.getId();
 		} else {
             // 器件 id 为 null 时,存默认值,以便于后期搜索时做空值过滤
             document.add(new StringField(SearchConstants.GOODS_CMP_ID_FIELD, NULL_VALUE, Store.YES));
+            primaryKey += "_" + NULL_VALUE;
         }
 
         if(goods.getProducts() != null){
@@ -391,6 +396,7 @@ public class ObjectToDocumentUtils {
             }
         }
 
+        document.add(new StringField(SearchConstants.GOODS_PRIMARY_KEY_FIELD, primaryKey, Store.YES));
         return document;
 	}
 

+ 3 - 1
mall-search/src/main/java/com/uas/search/util/SearchUtils.java

@@ -367,7 +367,9 @@ public class SearchUtils {
 			return SearchConstants.BRAND_ID_FIELD;
 		} else if (tableName.equals(SearchConstants.COMPONENT_TABLE_NAME)) {
 			return SearchConstants.COMPONENT_ID_FIELD;
-		} else if (tableName.equals(SearchConstants.ORDER_TABLE_NAME)) {
+		} else if (tableName.equals(SearchConstants.GOODS_TABLE_NAME)) {
+            return SearchConstants.GOODS_PRIMARY_KEY_FIELD;
+        } else if (tableName.equals(SearchConstants.ORDER_TABLE_NAME)) {
 			return SearchConstants.ORDER_ID_FIELD;
 		} else if (tableName.equals(SearchConstants.ORDER_INVOICE_TABLE_NAME)) {
 			return SearchConstants.ORDER_INVOICE_ID_FIELD;