Solr
  1. Solr
  2. SOLR-5524

Exception when using Query Function inside Scale Function

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 4.6
    • Fix Version/s: 4.7, 6.0
    • Component/s: None
    • Labels:
      None

      Description

      If you try to use the query function inside the scale function, it throws the following exception:
      org.apache.lucene.search.BooleanQuery$BooleanWeight cannot be cast to
      org.apache.lucene.queries.function.valuesource.ScaleFloatFunction$ScaleInfo

      Here is an example request that invokes this:
      http://localhost:8983/solr/collection1/select?q=*:*&fl=scale(query($x),0,5)&x=hello)

      1. SOLR-5524.patch
        2 kB
        Trey Grainger

        Activity

        Hide
        Trey Grainger added a comment -

        I just debugged the code and uncovered the problem. There is a Map (called context) that is passed through to each value source to store intermediate state, and both the query and scale functions are passing the ValueSource for the query function in as the KEY to this Map (as opposed to using some composite key that makes sense in the current context). Essentially, these lines are overwriting each other:

        Inside ScaleFloatFunction: context.put(this.source, scaleInfo); //this.source refers to the QueryValueSource, and the scaleInfo refers to a ScaleInfo object
        Inside QueryValueSource: context.put(this, w); //this refers to the same QueryValueSource from above, and the w refers to a Weight object

        As such, when the ScaleFloatFunction later goes to read the ScaleInfo from the context Map, it unexpectedly pulls the Weight object out instead and thus the invalid case exception occurs. The NoOp multiplication works because it puts an "different" ValueSource between the query and the ScaleFloatFunction such that this.source (in ScaleFloatFunction) != this (in QueryValueSource).

        Show
        Trey Grainger added a comment - I just debugged the code and uncovered the problem. There is a Map (called context) that is passed through to each value source to store intermediate state, and both the query and scale functions are passing the ValueSource for the query function in as the KEY to this Map (as opposed to using some composite key that makes sense in the current context). Essentially, these lines are overwriting each other: Inside ScaleFloatFunction: context.put(this.source, scaleInfo); //this.source refers to the QueryValueSource, and the scaleInfo refers to a ScaleInfo object Inside QueryValueSource: context.put(this, w); //this refers to the same QueryValueSource from above, and the w refers to a Weight object As such, when the ScaleFloatFunction later goes to read the ScaleInfo from the context Map, it unexpectedly pulls the Weight object out instead and thus the invalid case exception occurs. The NoOp multiplication works because it puts an "different" ValueSource between the query and the ScaleFloatFunction such that this.source (in ScaleFloatFunction) != this (in QueryValueSource).
        Hide
        Trey Grainger added a comment -

        Simple patch. Just changing the ScaleFloatFunction function to use itself as the key instead of the ValueSource it is using internally (it's first parameter). This seems consistent with how other ValueSources (such as the QueryValueSource) work, and it fixes the issue at hand.

        Show
        Trey Grainger added a comment - Simple patch. Just changing the ScaleFloatFunction function to use itself as the key instead of the ValueSource it is using internally (it's first parameter). This seems consistent with how other ValueSources (such as the QueryValueSource) work, and it fixes the issue at hand.
        Hide
        Ryan Ernst added a comment -

        Is there really a reason the key needs to be an object? Why not just a string like "scaleInfo"?

        Show
        Ryan Ernst added a comment - Is there really a reason the key needs to be an object? Why not just a string like "scaleInfo"?
        Hide
        Yonik Seeley added a comment -

        Is there really a reason the key needs to be an object? Why not just a string like "scaleInfo"?

        Two different scale functions in a single function query would then clash.

        Show
        Yonik Seeley added a comment - Is there really a reason the key needs to be an object? Why not just a string like "scaleInfo"? Two different scale functions in a single function query would then clash.
        Hide
        ASF subversion and git services added a comment -

        Commit 1547581 from Yonik Seeley in branch 'dev/trunk'
        [ https://svn.apache.org/r1547581 ]

        docs: SOLR-552 should be SOLR-5524

        Show
        ASF subversion and git services added a comment - Commit 1547581 from Yonik Seeley in branch 'dev/trunk' [ https://svn.apache.org/r1547581 ] docs: SOLR-552 should be SOLR-5524
        Hide
        ASF subversion and git services added a comment -

        Commit 1547584 from Yonik Seeley in branch 'dev/branches/branch_4x'
        [ https://svn.apache.org/r1547584 ]

        docs: SOLR-552 should be SOLR-5524

        Show
        ASF subversion and git services added a comment - Commit 1547584 from Yonik Seeley in branch 'dev/branches/branch_4x' [ https://svn.apache.org/r1547584 ] docs: SOLR-552 should be SOLR-5524
        Hide
        Yonik Seeley added a comment -

        Committed. Thanks Trey!

        Show
        Yonik Seeley added a comment - Committed. Thanks Trey!

          People

          • Assignee:
            Yonik Seeley
            Reporter:
            Trey Grainger
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development