Los complementos SOLR de Dice.com para realizar una búsqueda personalizada y recomendaciones (a través del complemento de retroalimentación de relevancia) y la búsqueda conceptual / semántica (a través del complemento de retroalimentación no supervisado).
Se puede encontrar un archivo JAR pre-construido en la carpeta ./target . El proyecto contiene un archivo maven pom.xml que también se puede usar para construirlo desde la fuente.
Si hay una versión particular de Solr para la que necesita esto, cree un problema de GitHub y veré qué puedo hacer. Para compilarlo manualmente para una versión específica, use Maven para compilar los complementos utilizando el archivo pom.xml y actualice las versiones de las bibliotecas Solr y Lucene en ese archivo, y use Maven para atraer esas dependencias. Luego corrige cualquier error de compilación.
Consulte las pautas oficiales de SOLR para registrar complementos con SOLR. Básicamente, esto implica simplemente dejar caer el archivo JAR en una de las carpetas que Solr verifica los archivos de clase y JAR en la recarga de núcleo.
A continuación se muestra una configuración de controlador de solicitud de ejemplo para SolrConfig.xml, con comentarios que describen los parámetros principales:
<requestHandler name="/rf" class="org.dice.solrenhancements.relevancyfeedback.RelevancyFeedbackHandler">
<lst name="defaults">
<str name="omitHeader">true</str>
<str name="wt">json</str>
<str name="indent">true</str>
<!-- Regular query configuration - query parser used when parsing the rf query-->
<str name="defType">lucene</str>
<!-- fields returned -->
<str name="fl">jobTitle,skill,company</str>
<!-- fields to match on-->
<str name="rf.fl">skillFromSkill,extractTitles</str>
<!-- field weights. Note that term weights are normalized so that each field is weighted exactly in this ratio
as different fields can get different numbers of matching terms-->
<str name="rf.qf">skillFromSkill^3 extractTitles^4.5</str>
<int name="rows">10</int>
<!-- How many terms to extract per field (max) -->
<int name="rf.maxflqt">10</int>
<bool name="rf.boost">true</bool>
<!-- normalize the weights for terms in each field (custom to dice rf, not present in solr MLT) -->
<bool name="rf.normflboosts">true</bool>
<!-- Take the raw term frequencies (false) or log of the term frequenies (true) -->
<bool name="rf.logtf">true</bool>
<!-- Minimum should match settings for the rf query - determines what proportion of the terms have to match -->
<!-- See Solr edismax mm parameter for specifics -->
<bool name="rf.mm">25%</bool>
<!-- Returns the top k terms (see regular solr MLT handler) -->
<str name="rf.interestingTerms">details</str>
<!-- Turns the rf query into a boost query using a multiplicative boost, allowing for boosting -->
<str name="rf.boostfn"></str>
<!-- q parameter - If you want to execute one query, and use the rf query to boost the results (e.g. for personalizing search),
pass the user's query into this parameter. Can take regular query syntax e.g.rf.q={!edismax df=title qf=.... v=$qq}&qq=Java
The regular q parameter is reserved for the rf query (see abpve)
-->
<str name="q"></str>
<!-- Query parser to use for the q query, if passed -->
<str name="defType"></str>
<!-- rf.q parameter - Note that the regular q parameter is used only for personalized search scenarios, where you have a main query
and you want to use the rf query generated to boost the main queries documents. Typically the rf.q query is a query that identifies
one or more documents, e.g. rf.q=(id:686867 id:98928980 id:999923). But it cam be any query. Note that it will process ALL documents
matched by the q query (as it's intended mainly for looking up docs by id), so use cautiously.
-->
<str name="rf.q"></str>
<!-- query parser to use for the rf.q query -->
<str name="rf.defType"></str>
<!-- Settings for personalized search - use the regular parameter names for the query parser defined by defType parameter -->
<str name="df">title</str>
<str name="qf"> company_text^0.01 title^12 skill^4 description^0.3</str>
<str name="pf2">company_text^0.01 title^12 skill^4 description^0.6</str>
<!-- Content based recommendations settings (post a document to the endpoint in a POST request). The stream.body and stream.head are form parameters
You can send them in a GET request, but a POST handles larger data. If you have really large documents, you will need to change the buffer settings
so that the request doesn't blow the buffer limits in Solr or your web server.
-->
<!-- Fields used for processing documents posted to the stream.body and stream.head parameters in a POST call -->
<str name="stream.head.fl">title,title_syn</str>
<str name="stream.body.fl">extractSkills,extractTitles</str>
<!-- pass a url in this parameter for Solr to download the webpage, and process the Html using the fields configured in the stream.qf parameters -->
<str name="stream.url"></str>
<!-- Note that we have two different content stream fields to pass over in the POST request. This allows different analyzers to be appkied to each.
For instance, we pass the job title into the stream.head field and parse out job titles, while we pass the job description to the stream.head parameter
to parse out skills -->
<!-- Pass the document body in this parameter as a form parameter. Analysed using the stream.body.fl fields-->
<str name="stream.body"></str>
<!-- Pass the second document field in this parameter. Analysed using the stream.head.fl fields-->
<str name="stream.head"></str>
<!-- Specifies a separate set of field weights to apply when procesing a document posted to the request handler via the
stream.body and stream.head parameters -->
<str name="stream.qf">extractSkills^4.5 extractTitles^2.25 title^3.0 title_syn^3.0</str>
</lst>
</requestHandler>
http: // localhost: 8983/solr/jobs/rf? Q = id: 11F407D319D6CC707437FAD874A097C0+ID: A2FD2F2E 34667D61FADCDCABFD359CF4 & ROWS = 10 & DF = Title & fl = Title, Habilidades, Geocode, Ciudad, Estado y WT = JSON
{
"match":{
"numFound":2,
"start":0,
"docs":[
{
"id":"a2fd2f2e34667d61fadcdcabfd359cf4",
"title":"Console AAA Sports Video Game Programmer.",
"skills":["Sports Game Experience a plus.",
"2-10 years plus Console AAA Video Game Programming Experience"],
"geocode":"38.124447,-122.55051",
"city":"Novato",
"state":"CA"
},
{
"id":"11f407d319d6cc707437fad874a097c0",
"title":"Game Engineer - Creative and Flexible Work Environment!",
"skills":["3D Math",
"Unity3d",
"C#",
"3D Math - game programming",
"game programming",
"C++",
"Java"],
"geocode":"33.97331,-118.243614",
"city":"Los Angeles",
"state":"CA"
}
]
},
"response":{
"numFound":5333,
"start":0,
"docs":[
{
"title":"Software Design Engineer 3 (Game Developer)",
"skills":["C#",
"C++",
"Unity"],
"geocode":"47.683647,-122.12183",
"city":"Redmond",
"state":"WA"
},
{
"title":"Game Server Engineer - MMO Mobile Gaming Start-Up!",
"skills":["AWS",
"Node.JS",
"pubnub",
"Websockets",
"pubnub - Node.JS",
"Vagrant",
"Linux",
"Git",
"MongoDB",
"Jenkins",
"Docker"],
"geocode":"37.777115,-122.41733",
"city":"San Francisco",
"state":"CA"
},...
]
}
}
A continuación se muestra una configuración de controlador de solicitud de ejemplo para SolrConfig.xml, con comentarios que describen los parámetros principales:
<requestHandler name="/ufselect" class="org.dice.solrenhancements.unsupervisedfeedback.UnsupervisedFeedbackHandler">
<lst name="defaults">
<str name="omitHeader">true</str>
<str name="wt">json</str>
<str name="indent">true</str>
<!-- Regular query configuration -->
<str name="defType">edismax</str>
<str name="df">title</str>
<str name="qf">title^1.5 skills^1.25 description^1.1</str>
<str name="pf2">title^3.0 skills^2.5 description^1.5</str>
<str name="mm">1</str>
<str name="q.op">OR</str>
<str name="fl">jobTitle,skills,company</str>
<int name="rows">30</int>
<!-- Unsupervised Feedback (Blind Feedback) query configuration-->
<str name="uf.fl">skillsFromskills,titleFromJobTitle</str>
<!-- How many docs to extract the top terms from -->
<str name="uf.maxdocs">50</str>
<!-- How many terms to extract per field (max) -->
<int name="uf.maxflqt">10</int>
<bool name="uf.boost">true</bool>
<!-- Relative per-field boosts on the extracted terms (similar to edismax qf parameter -->
<!-- NOTE: with uf.normflboosts=true, all terms are normalized so that the total importance of each
field on the query is the same, then these relative boosts are applied per field-->
<str name="uf.qf">skillsFromskills^4.5 titleFromJobTitle^6.0</str>
<!-- Returns the top k terms (see regular solr MLT handler) -->
<str name="uf.interestingTerms">details</str>
<!-- unit-length norm all term boosts within a field (recommended) - see talk for details -->
<bool name="uf.normflboosts">true</bool>
<!-- use raw term clounts or log term counts? -->
<bool name="uf.logtf">false</bool>
</lst>
</requestHandler>
http: // localhost: 8983/solr/diceJobscp/UFSelect? Q = Machine+Learning+Engineer & Start = 0 & Rows = 10 & UF.Logtf = False & fl = Título, Habilidades, Geocode, Ciudad, Estado y FQ = {! Geofilt+Sfield = JobendeCageOcode+D = 48+PT = 39.6955, -105.0841} & wt = json
{
"match":
{
"numFound":7729,
"start":0,
"docs":[
{
"title":"NLP/Machine Learning Engineer",
"skills":["Linux",
"NLP (Natural Language Processing)",
"SQL",
"Bash",
"Python",
"ML (Machine Learning)",
"JavaScript",
"Java"],
"geocode":"42.35819,-71.050674",
"city":"Boston",
"state":"MA"
},
{
"title":"Machine Learning Engineer",
"skills":["machine learning",
"java",
"scala"],
"geocode":"47.60473,-122.32594",
"city":"Seattle",
"state":"WA"
},
{
"title":"Machine Learning Engineer - REMOTE!",
"skills":["Neo4j",
"Hadoop",
"gensim",
"gensim - C++",
"Java",
"R",
"MongoDB",
"elastic search",
"sci-kit learn",
"Python",
"C++"],
"geocode":"37.777115,-122.41733",
"city":"San Francisco",
"state":"CA"
},...
]
}
Si bien se basa libremente en el código y el algoritmo del controlador Solr MLT (que es solo el algoritmo Rocchio), existen algunas diferencias clave en el diseño del algoritmo. El controlador MLT toma los términos K superiores en todos los campos configurados al construir la consulta MLT. Si tiene un campo que tiene un vocabulario más amplio que los otros campos, la frecuencia de documento promedio de un término será menor que en otros campos con vocabularios más pequeños. Esto significa que estos términos tendrán puntajes de IDF relativos altos y tienden a dominar los términos superiores seleccionados por el controlador Solr MLT. Nuestro controlador de solicitud toma los principales términos K por campo. También asegura que no importa cuántos términos coincidan por campo (hasta el límite configurado), ese campo tiene la misma ponderación en la consulta resultante que todos los demás campos, antes de que se aplican los pesos específicos del campo especificados en el parámetro RF.QF. Este es el segundo problema con el controlador Solr MLT que abordamos. También proporcionamos mucha funcionalidad adicional. Permitimos pasar las transmisiones de contenido, coincidir con múltiples documentos (más como 'estos' en lugar de más como 'esto'), aplicando el analizador de consulta de Boost a la consulta MLT resultante para permitir que se aplique cualquier impulso solr arbitrario (multiplicativo). Y apoyamos el parámetro MM, por lo que podemos obligar a los documentos a regresar que solo coinciden con un % establecido de los términos principales.
Si desea utilizar esto para realizar la personalización de búsqueda, como se demuestra en mi charla de Lucene Revolution 2017, debe aprobar la consulta de búsqueda actual del usuario utilizando el parámetro Q regular, y la información utilizada para generar el Rocchio se pasa a través del parámetro RF.Q (cuando se usa los documentos para generar el contenido de Rocchio) o a través de los parámetros de transmisión de contenido (rf.sream.head y rf.stream. Sin embargo, tenga en cuenta que los aumentos aplicados a los términos en la consulta de Rocchio no son de pesos comparativos para los de su consulta de usuario, debido al proceso de normalización que aplica el algoritmo. Por lo tanto, deberá experimentar con diferentes valores de RF.QF hasta que encuentre el nivel de influencia correcto en su consulta, en función de su configuración de búsqueda. Además, dado que la consulta de Rocchio generada para cada usuario es probablemente la misma en la sesión de búsqueda del usuario (dependiendo de su caso de uso, por supuesto), una forma más eficiente de usar esto para hacer personalización es simplemente usar el controlador de RF para generar la consulta de Rochio para usted una vez que el usuario llegue a la consulta de los usuarios. El controlador devuelve la consulta Rocchio en el parámetro RF.Query en la respuesta. Si desea usar el controlador solo para obtener la consulta (y no ejecutar la búsqueda), puede establecer el parámetro de filas en 0. También puede iterar sobre el conjunto de 'términos interesantes' devueltos por el algoritmo, junto con sus pesas, si establece rf.interestingterms = detalles, y usar esto para construir su consulta de valores.
Además de garantizar que esto funcione con más versiones de SOLR (deje los comentarios sobre qué versiones desean), hay una serie de mejoras posibles:
Si tiene una solicitud de función, envíela a la lista de problemas. Si tiene preguntas, ese también es un buen lugar para publicarlas, pero también puede comunicarse conmigo en [email protected] si no hace aquí.