2016-01-29 23 views
3

我是新來Elasticsearch,我想知道,如果這樣做,這是可能的:從倒排索引中高頻方面的排列順序串Elasticsearch

我有一堆地址字符串,我要排序的字符串中最重複的術語。

例如:

1. Shop no 1 ABC Lane City1 - Zipcode1 
2. Shop no 2 EFG Lane City1 - Zipcode2 
3. Shop no 1 XYZ Lane City2 - Zipcode3 
4. Shop no 3 ABC Lane City1 - Zipcode1 

我真正需要的是一羣人一起在字符串中的最常用的術語。

所以排序輸出應該是什麼前面的例子是:

1. Shop no 1 ABC Lane City1 - Zipcode1 
    4. Shop no 3 ABC Lane City1 - Zipcode1 # Because 1 and 2 have the most common words in them. 
    2. Shop no 2 EFG Lane City1 - Zipcode2 # Second most common words with 1 and 4. 
    3. Shop no 1 XYZ Lane City2 - Zipcode3 # Not all that many common terms amongst them. 

我不知道如何去它的主意。 我知道我可以將每個字符串作爲查詢來獲取最接近查詢結果的結果。 但我有十萬行,因此它似乎並不是一個有效的選項。

如果我可以只是matchall()sortterm過濾器每個字符串中重複出現的術語數量最多,這將是非常有用的。

在倒排索引中包含大部分相似單詞的文檔上可以有排序嗎?

這裏是我的數據怎麼看起來樣品引擎收錄: Sample Addresses

+0

我不知道有關elasticsearch,但python至少可以做一個計數器的單詞,然後使用它建立一個關鍵函數與排序使用,比如說每個單詞的計數總和term to sort – Copperfield

+1

我已經回答並展示瞭如何使用簡單的(簡單的)python方法來使用餘弦相似度。但是,如果您依賴發佈彈性搜索查詢,則應該查看MLT查詢(https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html )。 – ferdy

回答

3

解決方案

我已經使用https://stackoverflow.com/a/15174569/61903計算兩個cosine similarity字符串(學分@vpekar)作爲相似度的基礎算法。通常我把所有的字符串放到一個列表中。然後我將索引參數i設置爲0,只要它在列表長度的範圍內,就循環遍歷我。在那個循環中,我重複了從i + 1到length(list)的位置p。然後我找到list [i]和list [p]之間的最大餘弦值。兩個文本字符串都將放入一個列表中,以便在以後的相似度計算中不考慮它們。兩個文本字符串都將與餘弦值一起放入結果列表中,數據結構爲VectorResult。

之後,列表按餘弦值排序。我們現在具有唯一的具有遞減餘弦,又名相似值的字符串對。 HTH。

import re 
import math 
import timeit 

from collections import Counter 

WORD = re.compile(r'\w+') 


def get_cosine(vec1, vec2): 
    intersection = set(vec1.keys()) & set(vec2.keys()) 
    numerator = sum([vec1[x] * vec2[x] for x in intersection]) 

    sum1 = sum([vec1[x] ** 2 for x in vec1.keys()]) 
    sum2 = sum([vec2[x] ** 2 for x in vec2.keys()]) 
    denominator = math.sqrt(sum1) * math.sqrt(sum2) 

    if not denominator: 
     return 0.0 
    else: 
     return float(numerator)/denominator 


def text_to_vector(text): 
    words = WORD.findall(text) 
    return Counter(words) 


class VectorResult(object): 
    def __init__(self, cosine, text_1, text_2): 
     self.cosine = cosine 
     self.text_1 = text_1 
     self.text_2 = text_2 

    def __eq__(self, other): 
     if self.cosine == other.cosine: 
      return True 
     return False 

    def __le__(self, other): 
     if self.cosine <= other.cosine: 
      return True 
     return False 

    def __ge__(self, other): 
     if self.cosine >= other.cosine: 
      return True 
     return False 

    def __lt__(self, other): 
     if self.cosine < other.cosine: 
      return True 
     return False 

    def __gt__(self, other): 
     if self.cosine > other.cosine: 
      return True 
     return False 

def main(): 
    start = timeit.default_timer() 
    texts = [] 
    with open('data.txt', 'r') as f: 
     texts = f.readlines() 

    cosmap = [] 
    i = 0 
    out = [] 
    while i < len(texts): 
     max_cosine = 0.0 
     current = None 
     for p in range(i + 1, len(texts)): 
      if texts[i] in out or texts[p] in out: 
       continue 
      vector1 = text_to_vector(texts[i]) 
      vector2 = text_to_vector(texts[p]) 
      cosine = get_cosine(vector1, vector2) 
      if cosine > max_cosine: 
       current = VectorResult(cosine, texts[i], texts[p]) 
       max_cosine = cosine 
     if current: 
      out.extend([current.text_1, current.text_2]) 
      cosmap.append(current) 
     i += 1 

    cosmap = sorted(cosmap) 

    for item in reversed(cosmap): 
     print(item.cosine, item.text_1, item.text_2) 

    end = timeit.default_timer() 

    print("Similarity Sorting of {} strings lasted {} s.".format(len(texts), end - start)) 

if __name__ == '__main__': 
    main() 

結果

我用你sampple在http://pastebin.com/hySkZ4Pn作爲不會忽略測試數據:

1.0000000000000002 NO 15& 16 1ST FLOOR,2ND MAIN ROAD,KHB COLONY,GANDINAGAR YELAHANKA 
NO 15& 16 1ST FLOOR,2ND MAIN ROAD,KHB COLONY,GANDINAGAR YELAHANKA 

1.0 # 51/3 AGRAHARA YELAHANKA 
#51/3 AGRAHARA YELAHANKA 

0.9999999999999999 # C M C ROAD,YALAHANKA 
# C M C ROAD,YALAHANKA 

0.8728715609439696 # 1002/B B B ROAD,YELAHANKA 
0,B B ROAD,YELAHANKA 

0.8432740427115678 # LAKSHMI COMPLEX C M C ROAD,YALAHANKA 
# SRI LAKSHMAN COMPLEX C M C ROAD,YALAHANKA 

0.8333333333333335 # 85/1 B B M P OFFICE ROAD,KOGILU YELAHANKA 
#85/1 B B M P OFFICE NEAR KOGILU YALAHANKA 

0.8249579113843053 # 689 3RD A CROSS SHESHADRIPURAM CALLEGE OPP YELAHANKA 
# 715 3RD CROSS A SECTUR SHESHADRIPURAM CALLEGE OPP YELAHANKA 

0.8249579113843053 # 10 RAMAIAIA COMPLEX B B ROAD,YALAHANKA 
# JAMATI COMPLEX B B ROAD,YALAHANKA 

[ SNIPPED ] 

Similarity Sorting of 702 strings lasted 8.955146235887025 s.