Request one document or another depending on the specific field

Imagine a SolR index with documents like this

[
{
    ProductId: 123,
    Contract: abc
},
{
    ProductId: 123,
    Contract: def
},
{
    ProductId: 123
},
{
    ProductId: 567
},
{
    ProductId: 567,
    Contract: bar
}
]

      

  • There is always a document with a specific ProductId and without Contract

  • In addition, there can be from 0 to n documents with Contract

I need a query where I can use Contract

, and it should return me everything, ProductId

either the one that has the given one Contract

, if it exists, or the only document without it Contract

at all.

For example, I will make a request with Contract: def

(somehow) and it should give me this

[
{
    ProductId: 123,
    Contract: def
},
{
    ProductId: 567
}
]

      

  • Document with is Contract:abc

    not part of the result
  • Document with ProductId:123

    but without is Contract

    not part of the result
  • The document ProductId:567

    is part of the result, because there is no document with these ProductId

    andContractId: def

In other words, I need something like

  • Give me one document per ProductId

    and Contract:X

    XOR -Contract*

    , but not both.
+3


source to share


1 answer


Step 1 Write your request to return reports without Contracts, as well as all with matching contracts, but those with a matching contract have the highest score. This eliminates the problem for which you sometimes need the items in the results, which do not correspond to the Contract value: q=Contract:"def" OR (*:* -Contract:[* TO *])

. (*:* -Contract:[* TO *])

matches all records without contracts, but Contract:"def"

matches records with the correct contract. Entries that match Contract:"def"

naturally have a higher score than those without a contract, but if there are any problems or you just want to be sure, you can add a promotion to this offer Contract:"def"^2

.

Step 2 Add the Grouping Results to the query, configured so that you only ask for the highest score for any given ProductId

:

q=Contract:"def" OR (*:* -Contract:[* TO *])&group=true&group.field=ProductId

      




This requires the field to ProductId

be configured in your schema.xml

as multiValued="false"

, since multi-value fields cannot be used as groups. I also assume that you are using the Standard Query Parser , either the default one in yours solrconfig.xml

, or by adding an argument defType=lucene

when making the query.

The results should look something like this:

'grouped'=>{
'ProductId'=>{
  'matches'=>5,
  'groups'=>[{
      'groupValue'=>123,
      'doclist'=>{'numFound'=>3,'start'=>0,'docs'=>[
          {
            'ProductId'=>123,
            'Contract'=>'def'}]
      }},
    {
      'groupValue'=>567,
      'doclist'=>{'numFound'=>2,'start'=>0,'docs'=>[
          {
            'ProductId'=>567}]
      }}]}}}

      

Note that neither the values matches

nor the values numFound

in the result set tell you how many groups were returned, but the argument rows=XX

can be used to determine the maximum number of groups you want (in this case ProductIds).

0


source







All Articles