Explorar el Código

optimize SimilarValuesFieldComparator

sunyj hace 8 años
padre
commit
5cb23221e5

+ 95 - 0
src/main/java/com/uas/search/sort/DefaultFieldComparator.java

@@ -0,0 +1,95 @@
+package com.uas.search.sort;
+
+import org.apache.lucene.index.BinaryDocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.search.SimpleFieldComparator;
+
+import java.io.IOException;
+
+/**
+ * 默认排序实现
+ *
+ * @author sunyj
+ * @since 2017年7月3日 下午4:27:54
+ */
+abstract class DefaultFieldComparator extends SimpleFieldComparator<String> {
+
+    protected int AHEAD = -1;
+    protected int BEHIND = 1;
+    protected int PARALLEL = 0;
+    protected int UNKOWN = -2;
+    private String fieldname;
+    private String[] values;
+    private BinaryDocValues binaryDocValues;
+    private String top;
+    private String bottom;
+
+    DefaultFieldComparator(String fieldname, int numHits) {
+        this.fieldname = fieldname;
+        this.values = new String[numHits];
+    }
+
+    @Override
+    public int compare(int slot1, int slot2) {
+        String value1 = values[slot1];
+        String value2 = values[slot2];
+        return compare(value1, value2);
+    }
+
+    /**
+     * @param str1
+     * @param str2
+     * @return {@link #PARALLEL} 表示并列,{@link #BEHIND} 表示 str1 排在 str2 后面,{@link #AHEAD} 表示排在前面,{@link #UNKOWN} 表示需要进一步判断
+     */
+    protected int compare(String str1, String str2) {
+        if (str1 == null && str2 == null) {
+            return PARALLEL;
+        } else if (str1 == null) {
+            return BEHIND;
+        } else if (str2 == null) {
+            return AHEAD;
+        }
+        return UNKOWN;
+    }
+
+    @Override
+    public void copy(int slot, int doc) throws IOException {
+        values[slot] = binaryDocValues.get(doc).utf8ToString();
+    }
+
+    @Override
+    protected void doSetNextReader(LeafReaderContext context) throws IOException {
+        binaryDocValues = context.reader().getBinaryDocValues(fieldname);
+        if (binaryDocValues == null) {
+            throw new IllegalStateException("索引中不存在 binaryDocValues :" + fieldname);
+        }
+    }
+
+    @Override
+    public String value(int slot) {
+        return values[slot];
+    }
+
+    @Override
+    public void setBottom(int slot) {
+        bottom = values[slot];
+    }
+
+    @Override
+    public int compareBottom(int doc) throws IOException {
+        String value = binaryDocValues.get(doc).utf8ToString();
+        return compare(bottom, value);
+    }
+
+    @Override
+    public int compareTop(int doc) throws IOException {
+        String value = binaryDocValues.get(doc).utf8ToString();
+        return compare(top, value);
+    }
+
+    @Override
+    public void setTopValue(String value) {
+        top = value;
+    }
+
+}

+ 0 - 133
src/main/java/com/uas/search/sort/SimilarValuesFieldComparator.java

@@ -1,133 +0,0 @@
-package com.uas.search.sort;
-
-import com.uas.search.util.CharUtils;
-import org.apache.lucene.index.BinaryDocValues;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.search.SimpleFieldComparator;
-
-import java.io.IOException;
-
-/**
- * 用于联想词的排序
- * 
- * @author sunyj
- * @since 2017年7月3日 下午4:27:54
- */
-public class SimilarValuesFieldComparator extends SimpleFieldComparator<String> {
-
-	private String fieldname;
-	private String[] values;
-	private BinaryDocValues binaryDocValues;
-	private String top;
-	private String bottom;
-
-	public SimilarValuesFieldComparator(String fieldname, int numHits) {
-		this.fieldname = fieldname;
-		this.values = new String[numHits];
-	}
-
-	@Override
-	public int compare(int slot1, int slot2) {
-		String value1 = values[slot1];
-		String value2 = values[slot2];
-		return compare(value1, value2);
-	}
-
-	/**
-	 * 比较两个字符串 -> 优先级:数字 > 字母 > 其他字符(优先级视为相等)
-	 * 
-	 * @param str1
-	 * @param str2
-	 * @return 1表示str1排在str2后面,-1表示排在前面
-	 */
-	private int compare(String str1, String str2) {
-		if (str1 == null) {
-			return 1;
-		} else if (str2 == null) {
-			return -1;
-		}
-
-		if (str1.length() > str2.length()) {
-			return 1;
-		} else if (str1.length() < str2.length()) {
-			return -1;
-		}
-
-		char[] array1 = str1.toCharArray();
-		char[] array2 = str2.toCharArray();
-		for (int i = 0; i < array1.length; i++) {
-			char c1 = array1[i];
-			char c2 = array2[i];
-			// 优先级:数字 > 字母 > 其他字符(优先级视为相等)
-			if (CharUtils.isNumber(c1)) {
-				if (CharUtils.isNumber(c2)) {
-					// 均为数字,数字越小优先级越高
-					if (c1 > c2) {
-						return 1;
-					} else if (c1 < c2) {
-						return -1;
-					}
-					continue;
-				}
-				return -1;
-			} else if (CharUtils.isCharacter(c1)) {
-				if (CharUtils.isNumber(c2)) {
-					return 1;
-				} else if (CharUtils.isCharacter(c2)) {
-					c1 = CharUtils.toUpper(c1);
-					c2 = CharUtils.toUpper(c2);
-					// 均为字母,值越小优先级越高
-					if (c1 > c2) {
-						return 1;
-					} else if (c1 < c2) {
-						return -1;
-					}
-					continue;
-				}
-				return -1;
-			}
-		}
-		return 0;
-	}
-
-	@Override
-	public void copy(int slot, int doc) throws IOException {
-		values[slot] = binaryDocValues.get(doc).utf8ToString();
-	}
-
-	@Override
-	protected void doSetNextReader(LeafReaderContext context) throws IOException {
-		binaryDocValues = context.reader().getBinaryDocValues(fieldname);
-		if(binaryDocValues == null){
-			throw new IllegalStateException("索引中不存在 binaryDocValues :" + fieldname);
-		}
-	}
-
-	@Override
-	public String value(int slot) {
-		return values[slot];
-	}
-
-	@Override
-	public void setBottom(int slot) {
-		bottom = values[slot];
-	}
-
-	@Override
-	public int compareBottom(int doc) throws IOException {
-		String value = binaryDocValues.get(doc).utf8ToString();
-		return compare(bottom, value);
-	}
-
-	@Override
-	public int compareTop(int doc) throws IOException {
-		String value = binaryDocValues.get(doc).utf8ToString();
-		return compare(top, value);
-	}
-
-	@Override
-	public void setTopValue(String value) {
-		top = value;
-	}
-
-}

+ 61 - 8
src/main/java/com/uas/search/sort/SimilarValuesFieldComparatorSource.java

@@ -1,20 +1,73 @@
 package com.uas.search.sort;
 
-import java.io.IOException;
-
+import com.uas.search.util.CharUtils;
 import org.apache.lucene.search.FieldComparator;
 import org.apache.lucene.search.FieldComparatorSource;
 
+import java.io.IOException;
+
 /**
  * 用于联想词的排序
- * 
+ *
  * @author sunyj
  * @since 2017年7月3日 下午4:28:03
  */
 public class SimilarValuesFieldComparatorSource extends FieldComparatorSource {
-	@Override
-	public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
-			throws IOException {
-		return new SimilarValuesFieldComparator(fieldname, numHits);
-	}
+    @Override
+    public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
+            throws IOException {
+        return new DefaultFieldComparator(fieldname, numHits) {
+            @Override
+            protected int compare(String str1, String str2) {
+                int superCompare = super.compare(str1, str2);
+                if (superCompare != UNKOWN) {
+                    return superCompare;
+                }
+
+                // 优先级:数字 > 字母 > 其他字符(优先级视为相等)
+                if (str1.length() > str2.length()) {
+                    return 1;
+                } else if (str1.length() < str2.length()) {
+                    return -1;
+                }
+
+                char[] array1 = str1.toCharArray();
+                char[] array2 = str2.toCharArray();
+                for (int i = 0; i < array1.length; i++) {
+                    char c1 = array1[i];
+                    char c2 = array2[i];
+                    // 优先级:数字 > 字母 > 其他字符(优先级视为相等)
+                    if (CharUtils.isNumber(c1)) {
+                        if (CharUtils.isNumber(c2)) {
+                            // 均为数字,数字越小优先级越高
+                            if (c1 > c2) {
+                                return 1;
+                            } else if (c1 < c2) {
+                                return -1;
+                            }
+                            continue;
+                        }
+                        return -1;
+                    } else if (CharUtils.isCharacter(c1)) {
+                        if (CharUtils.isNumber(c2)) {
+                            return 1;
+                        } else if (CharUtils.isCharacter(c2)) {
+                            c1 = CharUtils.toUpper(c1);
+                            c2 = CharUtils.toUpper(c2);
+                            // 均为字母,值越小优先级越高
+                            if (c1 > c2) {
+                                return 1;
+                            } else if (c1 < c2) {
+                                return -1;
+                            }
+                            continue;
+                        }
+                        return -1;
+                    }
+                }
+                return 0;
+            }
+        };
+    }
+
 }