How to do a constant score query in Solr - solr

I'm using SolrNet to access a Solr index where I have a multivalue field called "tags". I want to perform the following pseudo-code query:
(tags:stack)^10 OR (tags:over)^5 OR (tags:flow)^2
where the term "stack" is being boosted by 10, "over" is being boosted by 5 and "flow" is being boosted by 2. The result I'm after is that results with "stack" will appear higher than those with "flow", etc.
The problem I'm having is that say "flow" only appears in a couple of documents, but "stack" appears in loads, then due to a high idf value, documents with "flow" appear above those with "stack".
When this was project was implemented straight in Lucene, I used ConstantScoreQuery and these eliminated the idf based the score solely on the boost value.
How can this be achieved with Solr and SolrNet, where I'm effectivly just passing Solr a query string? If it can't, is there an alternative way I can approach this problem?
Thanks in advance!

Solr 5.1 and later has this built into the query parser syntax via the ^= operator.
So just take your original query:
(tags:stack)^10 OR (tags:over)^5 OR (tags:flow)^2
And replace the ^ with ^= to change from boosted to constant:
(tags:stack)^=10 OR (tags:over)^=5 OR (tags:flow)^=2

I don't think there any way to directly express a ConstantScoreQuery in Solr, but it seems that range and prefix queries use ConstantScoreQuery under the hood, so you could try faking a range query, e.g. tags:[flow TO flow]
Alternatively, you could implement your own Solr QueryParser.

Related

SOLR boost query order is wrong

I want to retrieve some documents from SOLR and pass boosts to the field's so that they are returned in the order I request them (respectively the web request requests them). Therefore I add boosts to the desired ids:
q=myfield:"9125129"^10 OR
myfield:"9125417"^9 OR
myfield:"9124611"^8 OR
myfield:"9126980"^7 ...
fl=myfield
wt=csv
Unfortunately, this does not return the documents in the desired order:
myfield
9125129
9125417
9126980
9124611
If I change the query to
q=myfield:"9125129"^9 OR
myfield:"9125417"^8 OR
myfield:"9124611"^7 OR
myfield:"9126980"^6 ...
fl=myfield
wt=csv
(just for testing), the correct order is returned:
myfield
9125129
9125417
9124611
9126980
So it seems like SOLR does not like the double-digit boost value? But according to the spec this shouldn't be a problem. So what is actually the problem here and how can i request boosted fields with more than 10 documents?
Used SOLR version: 4.10.4
I found a documentation stating: "If absolute ordering is desired, a very high boost may be used."
And indeed, if I assign very highly spread boost values (e.g. 1000, 900, 80, 7), the sort order is correct.
But I guess it's open for discussion, whether this is a good practice and should be done like this. Seems a bit like guessing and using SOLR for something it was not designed for.
https://cwiki.apache.org/confluence/display/solr/SolrRelevancyCookbook#SolrRelevancyCookbook-BoostingRankingTerms

How to utilize a Lucene Query class (CommonTermsQuery) with SolrJ

I want to use Lucene's CommonTermsQuery class for a query executed with SolrJ, so how do I utilize Lucene's Query classes? And what are the differences between those classes and what appears to be Solr's query parsers?
Solr currently doesn't include a query parser that uses CommonTermsQuery, but you can add your own query parsers to Solr by compiling a .jar by yourself and then adding that jar in a <lib .. directive in solrconfig.xml.
There's an existing example on how to make a QParserPlugin for Solr with CommonTermsQuery available as a gist, so that's probably a good place to start for a custom plugin. You'll select the custom QueryParser through the standard {!syntax} in start of a query. Since SolrJ is just the client talking to a Solr server, the plugin itself has to be implemented and loaded on the server (or if you're running in SolrCloud / Cluster mode, on all servers).
A Query Parser takes free form text (which is what Solr is great at) and converts it into a set of Query classes for Lucene to execute (which represents the query, in the way that the query parser thought that the user wanted to express herself).
The differences between Solr's query parser and Lucene's query parser are several, but most people use the edismax or dismax query parser these days (these may have evolved into the Lucene QP over time as well unknown to me):
Differences in the Solr Query Parser include (these are from an older page on the Solr Wiki - I'm not sure if there's a more recent version available, but since Solr and Lucene's code merged into a single tree and got synchronized, I guess there are less new differences introduced compared to when they were separate projects):
Range queries [a TO z], prefix queries a*, and wildcard queries a*b are constant-scoring (all matching documents get an equal score). The scoring factors tf, idf, index boost, and coord are not used. There is no limitation on the number of terms that match (as there was in past versions of Lucene).
Lucene 2.1 has also switched to use ConstantScoreRangeQuery for its range queries.
A * may be used for either or both endpoints to specify an open-ended range query.
field:[* TO 100] finds all field values less than or equal to 100
field:[100 TO *] finds all field values greater than or equal to 100
field:[* TO *] matches all documents with the field
Pure negative queries (all clauses prohibited) are allowed.
-inStock:false finds all field values where inStock is not false
-field:[* TO *] finds all documents without a value for field
A hook into FunctionQuery syntax. Quotes will be necessary to encapsulate the function when it includes parentheses.
Example: _val_:myfield
Example: _val_:"recip(rord(myfield),1,2,3)"
Nested query support for any type of query parser (via QParserPlugin).
Quotes will often be necessary to encapsulate the nested query if it contains reserved characters.
Example: query:"{!dismax qf=myfield}how now brown cow"

How to perform an exact search in Solr

I implementing Solr search using an API. When I call it using the parameters as, "Chillout Lounge", it returns me the collection which are same/similar to the string "Chillout Lounge".
But when I search for "Chillout Lounge Box", it returns me results which don't have any of these three words.(in the DB there are values which have these 3 values, but they are not returned.)
According to me, Solr uses Fuzzy search, but when it is done it should return me some values, which will have at least one these value.
Or what could be the possible changes I should to my schema.XML, such that is would give me proper values.
First of all - "Fuzzy search" is a feature you'll have to ask for (by using ~ in standard Lucene query syntax).
If you're talking about regular searches, you can use q.op to select which operator to use. q.op=AND will make sure that all the terms match, while q.op=OR will make any document that contain at least one of the terms be returned. As long as you aren't using fq for this, the documents that match more terms should be scored higher (as the score will add up across multiple terms), and thus, be shown higher in the result set.
You can use the debug query feature in the web interface to see scores for each term for a document, and find out why the document was returned at all. If the document doesn't match any terms, it shouldn't be returned, unless you're asking for all documents to be returned.
Be aware that the analyzer chain defined for the field you're searching might affect what's considered a match and not.
You'll have to add a proper example to get a more detailed answer.

SOLR index time boost depending on the field value

Is it possible to boost a document on the indexing stage depending on the field value?
I'm indexing a text field pulled from the database. I would like to boost results that are shorter over the longer ones. So the value of boost should depend on the length of the text field.
This is needed to alter the standard SOLR behavior that in my case tends to return documents with multiple matches first.
Considering I have a field that stores the length of the document, the equivalent in the query of what I need at indexing would be:
q={!boost b=sqrt(length)}text:abcd
Example:
I have two items in the DB:
ABCDEBCE
ABCD
I always want to get ABCD first for the 'BC' query even though the other item contains the search query twice.
The other solution to the problem would be ability to 'switch off' the feature that scores multiple matches higher at query time. Don't know if that is possible either...
Doing this at index time is important as the hardware I run the SOLR on is not too powerful and trying to boost on query time returns with OutOfMemory Exception. (Even If I could work around that increasing memory for java I prefer to be on the safe side and implement the index the most efficient way possible.)
Yes and no - but how you do it depends on how you're indexing your documents.
As far as I know there's no way of resolving this only on the solr server side at the moment.
If you're using the regular XML based interface to submit documents, let the code that generates the submitted XML add boost=".." values to the field or to the document depending on the length of the text field.
You can check upon DIH Special Commands which has a $docBoost command
$docBoost : Boost the current doc. The value can be a number or the
toString of a number
However, there seems no $fieldBoost Command.
For you case though, if you are using DefaultSimilarity, shorter fields are boosted higher then longer fields in the Score calculation.
You can surely implement your own Simiarity class with a changed TF (Term Frequency) and LengthNorm Calculation as your needs.

How to boost fields in solr

I already have the boost determined before hand. I have a field in the solr index called boost1 . This boost field will have a value from 1 to 10 similar to google PR rank. This is the boost that should be applied to every query ran in solr. here are the fields in my index
Id
Title
Text
Boost1
The boost field should be apply to every query. I am trying to implement functionality similar to Google PR rank. Is there a way to do this using solr?
you can add the boost during query e.g.
q={!boost b=boost1}
How_can_I_boost_the_score_of_newer_documents
However, this may need to be added explicitly by you.
If you are using dismax or edismax with the request handler, The bf (Boost Functions) parameter could be used to boost the documents.
http://wiki.apache.org/solr/DisMaxQParserPlugin#bf_.28Boost_Functions.29
bf=boost1^0.5
This can be added to defaults with the request handler definition, so that they are applied to all the search queries.
you can use function queries to vary the amount of boost FunctionQuery
I think you need to use index time document boosts. See this if you are indexing XML or this if using DataImportHandler.

Resources