SolrNet with eDisMax using ANDs and ORs

651 views
Skip to first unread message

John Tabernik

unread,
Feb 7, 2014, 8:47:11 AM2/7/14
to sol...@googlegroups.com

I have been building Solr queries manually as strings and passing them to SolrNet.  The queries can be complicated combinations of ANDs and ORs like this.  Note that I am using eDisMax to allow for the complex nested query.

     _query_:"field1:[1 TO 10] OR
              field2:[1 TO 10] OR
              field3:[1 TO 10]"
      AND 
     _query_:"field4:(keyword)"
      AND 
     _query_:"field5:(keyword)"


This was working well, but looking into the API for SolrNet, I see there are objects I could use for each clause and then pull these objects together to form the complete query.  I would much rather implement this with that approach than build and concatenate the strings.

The API is well documented for ANDs and ORs but I need to have the ANDs and ORs grouped to handle the sitations like above--things like (a OR b) AND (c OR d).

I found an example that I think combines ANDs and ORs with parenthesis here.  Unfortunately, this assumes that I know the structure of the query in advance.  Instead, I will be creating a SolrNet query dynamically based on user input, so I can't hardcode a pattern like (a) && (b || c).
 
Any ideas how to do this with the SolrNet objects?

Mauricio Scheffer

unread,
Feb 7, 2014, 9:15:45 AM2/7/14
to sol...@googlegroups.com
Hi John, 

Have you seen SolrMultipleCriteriaQuery? (also documented in https://github.com/mausch/SolrNet/blob/master/Documentation/Querying.md#query-operators )



--
Mauricio


--
You received this message because you are subscribed to the Google Groups "SolrNet" group.
To unsubscribe from this group and stop receiving emails from it, send an email to solrnet+u...@googlegroups.com.
To post to this group, send email to sol...@googlegroups.com.
Visit this group at http://groups.google.com/group/solrnet.
For more options, visit https://groups.google.com/groups/opt_out.

John Tabernik

unread,
Feb 7, 2014, 9:46:26 AM2/7/14
to sol...@googlegroups.com
OK, I think I see how to do this.  For example, if I am building:
 
      ( a OR b) AND (c OR d)
 
I could build two objects like this:
 
	var aAndB = new SolrMultipleCriteriaQuery(new[] {new SolrQuery("a"), new SolrQuery("b")}, "OR")
	var cAndD = new SolrMultipleCriteriaQuery(new[] {new SolrQuery("c"), new SolrQuery("d")}, "OR")
 
 
Then I join these together this way:
 
        var result = new SolrMultipleCriteriaQuery(new[] {new SolrQuery("aAndB"), new SolrQuery("cAndD")}, "AND")
 
Thanks for your help, sorry I didn't think of this myself!!

John Tabernik

unread,
Jul 11, 2014, 9:01:38 AM7/11/14
to sol...@googlegroups.com
Per your suggestion, I am using SolrMultipleCriteriaQuery which is working perfectly.

I now have a requirement to perform some more complex processing on some query expressions--I will be using the Surround query parser.  LocalParams would be the perfect way to set the query parser per expression, but there is an issue with that.

I have been building query chunks as AbstractSolrQuery objects, then combining them with SolrMultipleCriteriaQuery.  However AbstractSolrQuery does not allow me to add LocalParams.

Any suggestions on the best way to approach this?

Here is a simplified chunk of code showing what I am doing now:

        public AbstractSolrQuery GetSearchExpression()
        {
            AbstractSolrQuery expression;

            if (fieldIsNumeric)
            {
                expression = GetSearchExpressionForNumber();
            }
            else
            {
                expression = GetSearchExpressionForText();
            }

            if (Boost != 1 && Boost != 1)
            {
                expression = expression.Boost(Boost);
            }

            if (isNot)
            {
                expression = expression.Not();
            }

            return expression;
        }


        private AbstractSolrQuery GetSearchExpressionForNumber()
        {
            AbstractSolrQuery expression;

            if (!CriteriaIsRange())
            {
                if (EqualsValue == "*")
                {
                    expression = new SolrHasValueQuery(FieldName);
                }
                else
                {
                    expression = new SolrQueryByField(FieldName, EqualsValue);
                }
            }
            else
            {
                expression = new SolrQueryByRange<decimal?>(FieldName, minValue, maxValue);
            }

            return expression;
        }


        private SolrQuery GetSearchExpressionForText()
        {
            // this is where I would want to conditionally set the parser to edismax or surround
            return new SolrQueryByField(FieldName, EqualsValue) { Quoted = false };
        }

Mauricio Scheffer

unread,
Jul 11, 2014, 10:54:37 AM7/11/14
to sol...@googlegroups.com
However AbstractSolrQuery does not allow me to add LocalParams.

Sure it can. The example documented in https://github.com/mausch/SolrNet/blob/master/Documentation/Querying.md#localparams shows a LocalParam attached to a SolrQuery which inherits from AbstractSolrQuery.

The problem seems to be that you're trying to make that GetSearchExpressionForText function return SolrQuery.




--
Mauricio


--
You received this message because you are subscribed to the Google Groups "SolrNet" group.
To unsubscribe from this group and stop receiving emails from it, send an email to solrnet+u...@googlegroups.com.
To post to this group, send email to sol...@googlegroups.com.
Visit this group at http://groups.google.com/group/solrnet.
For more options, visit https://groups.google.com/d/optout.

John Tabernik

unread,
Jul 11, 2014, 11:32:08 AM7/11/14
to sol...@googlegroups.com
That was a typo on my part, GetSearchExpressionForText should have AbstractSolrQuery as the return type.

I am executing queries against potentially different cores, so my queries are "core-agnostic", which I think is preventing me from using the ISolrOperations syntax:
ISolrOperations<Product> solr = ...
var products = solr.Query(new LocalParams {{"type", "dismax"},{"qf", "myfield"}} + new SolrQuery("solr rocks"));
I don't know that I will be working against the "Product" core when I create the query, if that makes sense.  I think I saw documentation on how to solve this, so I can then get LocalParams associated with each query term.

Thanks very much for your reply!!

John Tabernik

unread,
Jul 11, 2014, 11:40:14 AM7/11/14
to sol...@googlegroups.com
Per this page:  https://github.com/mausch/SolrNet/blob/master/Documentation/Mapping.md#fully-loose-mapping

I think I can use Fully Loose Mappings to get around the core issue by referencing them this way:
ISolrOperations<Dictionary<string, object>> solr = ...

Thanks so much, SolrNet is an amazing tool!

Mauricio Scheffer

unread,
Jul 11, 2014, 11:57:36 AM7/11/14
to sol...@googlegroups.com
I generally don't recommend using ISolrOperations<Dictionary<string, object>> as it's untyped, except maybe if you're working at the "raw data" level or to use it as a basis for your own typed abstraction.



--
Mauricio


--

John Tabernik

unread,
Jul 11, 2014, 1:25:51 PM7/11/14
to sol...@googlegroups.com
Actually, I don't need to do this after all because all of my cores have the same type.

I am switching to the StructureMap approach to create multiple cores with the same type.  Thanks again for your help!
Reply all
Reply to author
Forward
0 new messages