関数クエリ
関数クエリを使用すると、1 つ以上の数値フィールドの実際の値を使用して関連性のスコアを生成できます。
関数クエリは、DisMax クエリパーサ、拡張 DisMax (eDisMax) クエリパーサ、および標準クエリパーサでサポートされています。
関数クエリは *関数* を使用します。関数は、定数(数値または文字列リテラル)、フィールド、別の関数、またはパラメータ置換引数にすることができます。これらの関数を使用して、ユーザーの結果のランキングを変更できます。これらは、ユーザーの場所やその他の計算に基づいて結果のランキングを変更するために使用できます。
関数クエリの使用
関数は、関数呼び出しとして表現する必要があります(たとえば、a+b
ではなく sum(a,b)
)。
Solr クエリで関数クエリを使用する方法はいくつかあります。
-
関数引数を期待する明示的なクエリパーサ(例:
func
またはfrange
)を使用します。例:q={!func}div(popularity,price)&fq={!frange l=1000}customer_ratings
-
ソート式で。例:
sort=div(popularity,price) desc, score desc
-
クエリの結果で、関数の結果を疑似フィールドとしてドキュメントに追加します。例えば、
&fl=sum(x, y),id,a,b,c,score&wt=xml
出力は次のようになります。
... <str name="id">foo</str> <float name="sum(x,y)">40</float> <float name="score">0.343</float> ...
-
eDisMax クエリパーサの
boost
パラメータや、DisMax クエリパーサのbf
(ブースト関数)パラメータなど、関数を明示的に指定するためのパラメータで使用します。(bf
パラメータは実際には、空白で区切られた関数クエリのリストをとり、それぞれにオプションのブーストを付けます。bf
を使用する場合、単一関数クエリ内の内部空白を削除してください)。例:q=dismax&bf="ord(popularity)^0.5 recip(rord(price),1,1000,1000)^0.3"
-
_val_
キーワードを使用して、Lucene クエリパーサにインラインで関数クエリを導入します。例:q=_val_:mynumericfield _val_:"recip(rord(myfield),1,2,3)"
高速ランダムアクセス可能な関数のみを推奨します。
使用可能な関数
以下の表は、関数クエリで使用可能な関数をまとめたものです。
childfield(field) 関数
{!parent}
で検索する場合、一致した子ドキュメントのいずれかの指定されたフィールドの値を返します。これは、sort
パラメータでのみ使用できます。
構文例
-
sort=childfield(name) asc
は、第2引数として$q
を意味し、したがってq={!parent ..}..
を想定します。 -
sort=childfield(field,$bjq) asc
は、別のパラメータbjq={!parent ..}..
を参照します。 -
sort=childfield(field,{!parent of=…}…) desc
は、ブロック結合親クエリをインラインで指定できます。
def 関数
def
はデフォルトの略です。「field」フィールドの値を返し、フィールドが存在しない場合は指定されたデフォルト値を返します。exists()==true
の最初の値を生成します。
構文例
-
def(rating,5)
:このdef()
関数は、rating を返し、ドキュメントに rating が指定されていない場合は 5 を返します。 -
def(myfield, 1.0):
はif(exists(myfield),myfield,1.0)
と同等です。
dist 関数
n次元空間における2つのベクトル(点)間の距離を返します。べき乗と2つ以上のValueSourceインスタンスを入力として受け取り、2つのベクトル間の距離を計算します。各ValueSourceは数値でなければなりません。
渡されるValueSourceインスタンスの数は偶数でなければならず、このメソッドは前半が最初のベクトルを表し、後半が2番目のベクトルを表すと仮定します。
構文例
-
dist(2, x, y, 0, 0)
:(0,0)と(x,y)間のユークリッド距離を各ドキュメントに対して計算します。 -
dist(1, x, y, 0, 0)
:(0,0)と(x,y)間のマンハッタン距離(タクシー距離)を各ドキュメントに対して計算します。 -
dist(2, x,y,z,0,0,0)
:(0,0,0)と(x,y,z)間のユークリッド距離を各ドキュメントに対して計算します。 -
dist(1,x,y,z,e,f,g)
:各文字がフィールド名である(x,y,z)と(e,f,g)間のマンハッタン距離。
vectorSimilarity関数
n次元空間における2つのKnnベクトル間の類似度を返します。ベクトル要素のエンコーディング、類似度測定基準、および2つのValueSourceインスタンスを入力として受け取り、2つのベクトル間の類似度を計算します。
-
サポートされるエンコーディングは、
BYTE
、FLOAT32
です。 -
サポートされる類似度は、
EUCLIDEAN
、COSINE
、DOT_PRODUCT
です。
各ValueSourceはknnベクトル(フィールドまたは定数)でなければなりません。
構文例
-
vectorSimilarity(FLOAT32, COSINE, [1,2,3], [4,5,6])
:[1, 2, 3]と[4, 5, 6]間のコサイン類似度を各ドキュメントに対して計算します。 -
vectorSimilarity(FLOAT32, DOT_PRODUCT, vectorField1, vectorField2)
:'vectorField1'と'vectorField2'のベクトル間のドット積類似度を各ドキュメントに対して計算します。 -
vectorSimilarity(BYTE, EUCLIDEAN, [1,5,4,3], vectorField)
:'vectorField'のベクトルと定数ベクトル[1, 5, 4, 3]間のユークリッド類似度を各ドキュメントに対して計算します。
docfreq(field,val)関数
フィールド内の用語を含むドキュメントの数を返します。これは定数です(インデックス内のすべてのドキュメントで同じ値)。
用語が複雑な場合は引用符で囲むか、用語の値にパラメータ置換を使用できます。
構文例
-
docfreq(text,'solr')
-
…&defType=func
&q=docfreq(text,$myterm)&myterm=solr
field関数
指定された名前のフィールドの数値docValuesまたはインデックス付きの値を返します。最も単純な(単一引数)形式では、この関数は単一値フィールドでのみ使用でき、フィールド名を文字列として使用して呼び出すことができます。または、ほとんどの従来のフィールド名については、field(…)
構文を使用せずに、フィールド名自体をそのまま使用できます。
docValuesを使用する場合、オプションの第2引数を指定して、多値フィールドのmin
またはmax
値を選択できます。
フィールドに値がないドキュメントには0が返されます。
構文例 これらの3つの例はすべて同等です。
-
myFloatFieldName
-
field(myFloatFieldName)
-
field("myFloatFieldName")
最後の形式は、フィールド名が非標準的な場合に便利です。
-
field("my complex float fieldName")
多値docValuesフィールドの場合
-
field(myMultiValuedFloatField,min)
-
field(myMultiValuedFloatField,max)
hsin関数
ハバーサイン距離は、球面上を移動する場合の球上の2点間の距離を計算します。値はラジアンでなければなりません。hsin
は、関数がその出力をラジアンに変換するかどうかを指定するブール引数も受け取ります。
構文例
-
hsin(2, true, x, y, 0, 0)
idf関数
逆文書頻度。用語がすべてのドキュメント全体で一般的かまれかを測定する指標です。用語を含むドキュメントの数でドキュメントの総数を割り、その商の対数を取ることで得られます。tf
も参照してください。
構文例
-
idf(fieldName,'solr')
:fieldName
における用語'solr'
の出現頻度の逆数を測定します。
if関数
条件付き関数クエリを有効にします。if(test,value1,value2)
で
-
test
は、論理値(TRUEまたはFALSE)を返す論理値または式です。 -
test
がTRUEを返す場合、関数によって返される値はvalue1
です。 -
test
がFALSEを返す場合、関数によって返される値はvalue2
です。
式は、ブール値を出力する関数、または数値を返す関数(その場合、値0はfalseとして解釈されます)、または文字列を返す関数(その場合、空文字列はfalseとして解釈されます)にすることができます。
構文例
-
if(termfreq (cat,'electronics'),popularity,42)
:この関数は、各ドキュメントにcat
フィールドに「electronics」という用語が含まれているかどうかをチェックします。含まれている場合は、popularity
フィールドの値が返され、そうでない場合は42
の値が返されます。
linear関数
m*x+c
を実装します。ここで、m
とc
は定数、x
は任意の関数です。これはsum(product(m,x),c)
と同等ですが、単一の関数として実装されているため、わずかに効率的です。
構文例
-
linear(x,m,c)
-
linear(x,2,4)
:2*x+4
を返します。
map関数
入力関数x
のmin
とmax
(両端を含む)の範囲内に入る値を指定されたtarget
にマップします。引数min
とmax
は定数でなければなりません。引数target
とdefault
は定数または関数にすることができます。
x
の値がmin
とmax
の間にない場合、x
の値が返されるか、5番目の引数として指定されている場合はデフォルト値が返されます。
構文例
-
map(x,min,max,target)
-
map(x,0,0,1)
:0の値をすべて1に変更します。これは、デフォルトの0値を処理する際に役立ちます。
-
-
map(x,min,max,target,default)
-
map(x,0,100,1,-1)
:0
と100
の間の値をすべて1
に変更し、その他の値をすべて-1
に変更します。 -
map(x,0,100,sum(x,599),docfreq(text,solr))
:0
と100
の間の値をすべてx+599に変更し、その他の値をすべてフィールドtext内の用語'solr'の頻度に変更します。
-
max関数
引数として指定された複数の入れ子になった関数または定数の最大の数値を返します:max(x,y,…)
。max
関数は、別の関数またはフィールドを特定の定数で「底打ち」するのにも役立ちます。
単一の多値フィールドの最大値を選択するには、field(myfield,max)
構文を使用します。
構文例
-
max(myfield,myotherfield,0)
maxdoc関数
インデックス内のドキュメントの数を返します。削除済みとしてマークされているがまだパージされていないドキュメントも含みます。これは定数です(インデックス内のすべてのドキュメントで同じ値)。
構文例
-
maxdoc()
min関数
引数として指定された複数の入れ子になった関数または定数の最小の数値を返します:min(x,y,…)
。min
関数は、定数を使用して関数の「上限」を提供するのにも役立ちます。
単一の多値フィールドの最小値を選択するには、field(myfield,min)
構文を使用します。
構文例
-
min(myfield,myotherfield,0)
ms関数
引数の間のミリ秒単位の差を返します。日付は、UnixまたはPOSIX時間エポック、1970年1月1日午前0時UTCを基準としています。
引数は、DatePointField
、TrieDateField
、または定数日付またはNOW
に基づく日付計算にすることができます。
-
ms()
:ms(NOW)
と同等で、エポックからのミリ秒数を表します。 -
ms(a)
:引数が表すエポックからのミリ秒数を返します。 -
ms(a,b)
:bがaの前に発生するミリ秒数を返します(つまり、a - b)。
構文例
-
ms(NOW/DAY)
-
ms(2000-01-01T00:00:00Z)
-
ms(mydatefield)
-
ms(NOW,mydatefield)
-
ms(mydatefield, 2000-01-01T00:00:00Z)
-
ms(datefield1, datefield2)
norm(field)関数
指定されたフィールドにインデックスに格納されている「norm」を返します。これは、フィールドのSimilarityに従って、インデックス時のブーストと長さ正規化係数の積です。
構文例
-
norm(fieldName)
numdocs関数
インデックス内のドキュメントの数を返します。削除済みとしてマークされているがまだパージされていないドキュメントは含みません。これは定数です(インデックス内のすべてのドキュメントで同じ値)。
構文例
-
numdocs()
ord関数
Luceneインデックス順序(Unicode値によって辞書順にソート)で、そのフィールドの用語のインデックス付きリスト内のインデックス付きフィールド値の序数を1から返します。
言い換えると、特定のフィールドに対して、すべての値は辞書順にソートされます。この関数は、その順序付けにおける特定の値のオフセットを返します。フィールドは、ドキュメントごとに最大1つの値を持つ必要があります(多値ではありません)。フィールドに値がないドキュメントには0が返されます。
ord() はインデックス内の位置に依存し、他のドキュメントが挿入または削除されると変更される可能性があります。 |
下記のrord
も参照してください。
構文例
-
ord(myIndexedField)
-
特定のフィールドXに3つの値(「apple」、「banana」、「pear」)しかない場合、
ord(X)
は「apple」を含むドキュメントの場合は1
、「banana」を含むドキュメントの場合は2
などになります。
payload関数
指定された用語のデコードされたペイロードから計算されたfloat値を返します。
戻り値は、デコードされたペイロードのmin
、max
、またはaverage
を使用して計算されます。他の関数ではなく、特別なfirst
関数を使用することで、用語の列挙を短絡して、最初の用語のデコードされたペイロードのみを返すことができます。
指定されたフィールドは、floatまたはintegerペイロードエンコーディング機能(DelimitedPayloadTokenFilter
またはNumericPayloadTokenFilter
を介して)を持っている必要があります。用語にペイロードが見つからない場合は、デフォルト値が返されます。
-
payload(field_name,term)
:デフォルト値は0.0、average
関数が使用されます。 -
payload(field_name,term,default_value)
:デフォルト値は、定数、フィールド名、または別のfloatを返す関数にすることができます。average
関数が使用されます。 -
payload(field_name,term,default_value,function)
:関数値は、min
、max
、average
、またはfirst
にすることができます。
構文例
-
payload(payloaded_field_dpf,term,0.0,first)
product関数
カンマで区切られたリストで指定された複数の値または関数の積を返します。mul(…)
もこの関数のエイリアスとして使用できます。
構文例
-
product(x,y,…)
-
product(x,2)
-
mul(x,y)
query関数
指定されたサブクエリのスコア、またはクエリに一致しないドキュメントのデフォルト値を返します。任意のタイプのサブクエリは、パラメータの参照解除$otherparam
またはローカルパラメータのv
キーによるクエリ文字列の直接指定のいずれかによってサポートされます。
構文例
-
query(subquery, default)
-
q=product (popularity,query({!dismax v='solr rocks'})
:popularityとDisMaxクエリのスコアの積を返します。 -
q=product (popularity,query($qq))&qq={!dismax}solr rocks
:パラメータの参照解除を使用して、前のクエリと同等です。 -
q=product (popularity,query($qq,0.1))&qq={!dismax}solr rocks
:DisMaxクエリに一致しないドキュメントのデフォルトスコアを0.1に指定します。
recip関数
recip(x,m,a,b)
は、a/(m*x+b)
を実装する逆数関数を実行します。ここで、m
、a
、b
は定数であり、x
は任意の複雑な関数です。
a
と b
が等しく、x>=0
の場合、この関数は最大値 1
を持ち、x
が増加するにつれて減少します。a
と b
の値を同時に増やすと、関数の全体が曲線のより平坦な部分に移動します。これらの特性により、x
が rord(datefield)
の場合、最近のドキュメントをブーストするのに理想的な関数になります。
構文例
-
recip(myfield,m,a,b)
-
recip(rord(creationDate), 1,1000,1000)
scale 関数
関数 x
の値を、指定された minTarget
と maxTarget
(両端を含む)の間に収まるようにスケーリングします。現在の実装では、最小値と最大値を取得するために関数のすべての値を走査するため、正しいスケールを選択できます。
現在の実装では、ドキュメントが削除された場合や値がないドキュメントを区別できません。これらの場合、0.0
の値を使用します。つまり、値が通常すべて 0.0
より大きい場合でも、0.0
が最小値 min
としてマッピングされる可能性があります。このような場合、0.0
を実際の範囲内の値に変更する適切な map()
関数を回避策として使用できます。例:scale(map(x,0,0,5),1,2)
構文例
-
scale(x, minTarget, maxTarget)
-
scale(x,1,2)
:x の値を、すべての値が 1 以上 2 以下の範囲になるようにスケーリングします。
sqedist 関数
2ノルム(ユークリッド距離)を計算しますが、平方根を取らないため、かなりコストのかかる演算を節約できます。ユークリッド距離を気にするアプリケーションでは、実際の距離ではなく、距離の2乗を使用できることがよくあります。渡される ValueSource インスタンスの数は偶数でなければならず、このメソッドは前半が最初のベクトルを表し、後半が2番目のベクトルを表すと仮定しています。
構文例
-
sqedist(x_td, y_td, 0, 0)
strdist 関数
2つの文字列間の距離を計算します。Lucene のスペルチェッカー StringDistance
インターフェースを使用し、そのパッケージで使用可能なすべての機能を実装するだけでなく、Solr のリソース読み込み機能を使用して独自の機能をプラグインできます。strdist
は (string1, string2, distance measure) を受け取ります。
距離測定の可能な値は次のとおりです。
-
jw: Jaro-Winkler
-
edit: Levenstein または編集距離
-
ngram: NGramDistance。指定した場合は、ngram のサイズもオプションで渡すことができます。デフォルトは 2 です。
-
FQN:
StringDistance
インターフェースの実装の完全修飾クラス名。引数なしのコンストラクターが必要です。
構文例
-
strdist("SOLR",id,edit)
sum 関数
コンマで区切られたリストで指定された複数の値または関数の合計を返します。add(…)
をこの関数のエイリアスとして使用できます。
構文例
-
sum(x,y,…)
-
sum(x,1)
-
sum(sqrt(x),log(y),z,0.5)
-
add(x,y)
sumtotaltermfreq 関数
インデックス全体(つまり、そのフィールドのインデックス付きトークンの数)のフィールド内のすべての用語の totaltermfreq
値の合計を返します。(sumtotaltermfreq
を sttf
にエイリアス化します。)
構文例 doc1:(fieldX:A B C) と doc2:(fieldX:A A A A) の場合
-
docFreq(fieldX:A)
= 2(A は 2 つのドキュメントに表示されます) -
freq(doc2, fieldX:A)
= 4(A はドキュメント 2 に 4 回表示されます) -
totalTermFreq(fieldX:A)
= 5(A はすべてのドキュメントに 5 回表示されます) -
sumTotalTermFreq(fieldX)
= 7(fieldX
には、5 つの A、1 つの B、1 つの C があります)
tf 関数
用語頻度。フィールドの Similarity を使用して、指定された用語の用語頻度係数を返します。tf-idf
値は、単語がドキュメントに表示される回数に比例して増加しますが、ドキュメント内の単語の頻度によってオフセットされます。これは、一部の単語は一般的に他の単語よりも一般的であるという事実を制御するのに役立ちます。idf
も参照してください。
構文例
-
tf(text,'solr')
ブール関数
次の関数はブール関数であり、true または false を返します。ほとんどは if
関数の最初の引数として有用であり、一部は組み合わせることができます。他の場所で使用する場合は、'1' または '0' を生成します。
and 関数
オペランドのすべてが true と評価される場合にのみ、true の値を返します。
構文例
-
and(not(exists(popularity)),exists(price))
:price
フィールドに値があり、popularity
フィールドに値がないドキュメントに対してtrue
を返します。
xor 関数
論理的排他的論理和、または一方または他方であるが、両方ではない。
構文例
-
xor(field1,field2)
は、field1
またはfield2
のいずれかが true の場合にtrue
を返します。両方が true の場合は FALSE を返します。
exists 関数
フィールドのメンバーが存在する場合、true
を返します。
構文例
-
exists(author)
:"author" フィールドに値があるドキュメントに対してtrue
を返します。 -
exists(query(price:5.00))
:"price" が "5.00" に一致する場合、true
を返します。
関数クエリの例
Solr で関数クエリがどのように使用できるかをよりよく理解するために、仮のボックスの寸法(メートル単位の x、y、z)と、boxname
フィールドに格納された任意の名前をインデックスに格納するとします。findbox
という名前に一致するボックスを検索し、ボックスのボリュームに従ってランク付けしたいとします。クエリパラメータは次のようになります。
q=boxname:findbox _val_:"product(x,y,z)"
このクエリは、ボリュームに基づいて結果をランク付けします。計算されたボリュームを取得するには、結果のボリュームを含む score
を要求する必要があります。
&fl=*, score
ボックスの重量を weight
として格納するフィールドがあるとします。ボックスの密度でソートし、密度の値をスコアで返すには、次のクエリを送信します。
https://127.0.0.1:8983/solr/collection_name/select?q=boxname:findbox _val_:"div(weight,product(x,y,z))"&fl=boxname x y z weight score
関数によるソート
関数出力によってクエリ結果をソートできます。たとえば、距離で結果をソートするには、次のように入力します。
https://127.0.0.1:8983/solr/collection_name/select?q=*:*&sort=dist(2, point1, point2) desc
関数によるソートは擬似フィールドもサポートします。フィールドは動的に生成され、インデックス内の通常のフィールドであるかのように結果を返します。たとえば、
&fl=id,sum(x, y),score&wt=xml
は次を返します。
<str name="id">foo</str>
<float name="sum(x,y)">40</float>
<float name="score">0.343</float>