2011-10-20 4 views
3

GAEでの全文検索の代わりに、ソートされた結果セット、キーワード関連性、および2番目にソートされた結果セットを返すために以下のソリューションを使用しています。 )。私は最適化の提案や別のアプローチを探しています。セカンダリソートを使用したGAEテキスト検索

特定の検索では関連性の高い(キーワード一致の数で測定される)複数の検索結果が表示される可能性がありますが、元の検索クエリの順序を保持すると複雑さが増します今。何か案は?

ステップ1:あなたが蓄積することができ、グループ周波数リストは

#return a dictionary of keys, with their frequency of occurrence    
grouped_results = defaultdict(int)    
for key in results_key_list: 
    grouped_results[key] += 1    

sorted_results = [] 
known = set() 

#creates an empty list for each match frequency 
for i in range(len(search_terms)): 
    sorted_results.append([]) 

#using the original results ordering, 
#construct an array of results grouped and ordered by descending frequency 
for key in results_key_list: 
    if key in known: continue 
    frequency = grouped_results[key] 
    sorted_results[len(search_terms) - frequency].append(key) 
    known.add(key)   

#combine into a single list 
ordered_key_list = [] 
for l in sorted_results: 
    ordered_key_list.extend(l) 

del ordered_key_list[:offset] 
del ordered_key_list[limit:]  
result = SomeEntity.get(ordered_key_list) 

答えて

2
search_terms = ['a','b','c'] #User's search query, split into a list of strings 

元の順序を維持しながら:

results_key_list = [] 
search_terms = ['a','b','c'] #User's search query, split into a list of strings 

#query each search term and add the results to a list 
#yields a list of keys with frequency of occurance indicating relevance  
for item in search_terms: 
    subquery = SomeEntity.all(keys_only=True)     
    subquery.filter('SearchIndex = ', item) #SearchIndex is a StringListProperty 
    #more filters...    
    subquery.order('-DateCreated')     
    for returned_item in subquery: 
     results_key_list.append(str(returned_item))  

ステップ2を各検索語に一致するキーのリストを取得します。出現順のキーは であり、すべてのキー周波数を1回のパスで蓄積することができます。 その後、出現の順序によって、周波数を減少させることによって、ソートを行うために、ソートの安定性を利用してください:

keys_in_order_of_appearance = [] 
key_frequency = defaultdict(int) 

for item in search_terms: 
    subquery = SomeEntity.all(keys_only=True)     
    subquery.filter('SearchIndex = ', item) #SearchIndex is a StringListProperty 
    #more filters...    
    subquery.order('-DateCreated')     
    for returned_item in subquery: 
     key = str(returned_item) 
     if key not in key_frequency: 
      key_order_of_appearance.append(key) 
     key_frequency[key] += 1 

keys = keys_in_order_of_appearance[:] # order of appearance kept as secondary sort 
keys.sort(key=key_frequency.__getitem__, reverse=True) # descending freq as primary sort 
result = SomeEntity.get(ordered_key_list) 
+0

ありがとうございます!これはちょうど私が探していた削減の一種です。 –

2

ステップ1では、クエリオブジェクトを反復しています。この結果、20個のオブジェクトごとに1つのフェッチRPCが返されますが、これは非効率的で時間がかかります。代わりに、クエリオブジェクトのfetch(n)を呼び出します。nは返す結果の最大数です。これは1つのRPCだけです。それはまた、検索する検索結果の数を制限するという利点があります。私が「私」を検索すると、ステップ1でほぼすべてのレコードが処理されます。

また、文字列に - あなたはちょうど良いセットのキーを追加することができます。

しかし、私は個人的に「または」の検索が特に役に立たないと感じています。最初にすべての条件に一致するアイテムをランク付けしますが、必然的に無関係な結果の積み重ねや積み重ねが続くことになります。検索用語ごとに等価フィルタを使用して1つのクエリを実行するだけで、 'and'検索を行うことができます。

+0

コメントありがとうございます。私の場合、結果セットは一般的に狭いので(他のフィルタのため)、「OR」アプローチを取ることで、少なくともいくつかの結果が返され、ステミングがない場合には検索を少しでも寛容にします。つまり、特定の結果の数をターゲットにして最適化することができます。つまり、結果がN件未満の場合にのみ 'OR'の一致を探します。 –

+0

GAEがより完全な検索ライブラリを提供するのを待っている私のサイトのadsense検索に切り替えました。 SearchableModelに制限が多すぎるIMHO。 –