# ClassCastException when querying nested properties

**URL:** <https://discuss.elastic.co/t/classcastexception-when-querying-nested-properties/9163>\
**Category:** Elasticsearch\
**Created:** [September 26, 2012, 7:03pm UTC](https://discuss.elastic.co/t/classcastexception-when-querying-nested-properties/9163 "2012-09-26T19:03:42Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![kamil\_2](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kamil\_2](https://discuss.elastic.co/u/kamil_2)\
**Post date:** [September 26, 2012, 7:03pm UTC](https://discuss.elastic.co/t/classcastexception-when-querying-nested-properties/9163/1 "2012-09-26T19:03:42Z")

</div>

I'm trying to query some properties in a nested object with a script sort  
and I'm running into some strange behaviour. I managed to contrive a small  
example that reproduces this.

First, create a new index and apply the attached mapping:

curl -X PUT [http://localhost:9200/widgets](http://localhost:9200/widgets)  
curl -X PUT [http://localhost:9200/widgets/widget/\_mapping](http://localhost:9200/widgets/widget/_mapping) -d @widget.json

Then add some objects to the index:

curl -X PUT [http://localhost:9200/widgets/widget/1](http://localhost:9200/widgets/widget/1) -d  
'{"id":1,"type":"pegasus","components":[{"id":1,"type":"honda  
civic"},{"id":2,"type":"mazda rx-8"}]}'  
curl -X PUT [http://localhost:9200/widgets/widget/2](http://localhost:9200/widgets/widget/2) -d  
'{"id":2,"type":"pegasus","components":[{"id":1,"type":"honda  
accord"},{"id":2,"type":""}]}'  
curl -X PUT [http://localhost:9200/widgets/widget/3](http://localhost:9200/widgets/widget/3) -d  
'{"id":3,"type":"unicorn","components":[{"id":3,"type":"toyota supra"}]}'  
curl -X PUT [http://localhost:9200/widgets/widget/4](http://localhost:9200/widgets/widget/4) -d  
'{"id":4,"type":"unicorn","components":[]}'

I'm trying to find all widgets that have a component with "id" 1 and I want  
to sort by the "type" value. Anything without that value should get sorted  
to the bottom (I'm using 'Z' for that below, though in practice I use  
character '\uffe0'). I use the following script:

ids = doc['components.id'];  
if (ids.empty || ids.values.length == 0)  
return 'Z';

types = doc['components.type'];  
if (!ids.multiValued)  
return types.value;

for (i = 0; i \< ids.values.length; i++)  
if (ids.values[i] == 2)  
return type.values[i];

return 'Z';

I'm running it with curl like so:

curl -X GET [http://localhost:9200/widgets/widget/\_search?pretty](http://localhost:9200/widgets/widget/_search?pretty) -d  
'{"sort":{"\_script":{"script":"ids=doc['''components.id'''];if(ids.empty||ids.values.length==0)return  
'''Z''';type=doc['''components.type'''];if(!ids.multiValued)return  
type.value;for(i=0;i\<ids.values.length;i++)if(ids.values[i]==2)return  
type.values[i];return '''Z''';","type":"string","order":"asc"}}}'

When I run this, some of the shards fail with a ClassCastException (full  
stack trace attached):

Caused by: java.lang.ClassCastException: [J cannot be cast to [Ljava.lang.  
Object;  
at org.elasticsearch.common.mvel2.optimizers.impl.refl.nodes.  
ArrayAccessorNest.getValue(ArrayAccessorNest.java:53)  
at org.elasticsearch.common.mvel2.optimizers.impl.refl.nodes.  
GetterAccessor.getValue(GetterAccessor.java:40)  
... 31 more

Any ideas about what I may be doing wrong or how I can fix this? Thanks.

Kamil

--

---

<div class="post-metadata">

**Author:** ![kamil\_2](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kamil\_2](https://discuss.elastic.co/u/kamil_2)\
**Post date:** [September 26, 2012, 11:22pm UTC](https://discuss.elastic.co/t/classcastexception-when-querying-nested-properties/9163/2 "2012-09-26T23:22:51Z")

</div>

My guess is that somewhere along the way through to the MVEL compiler  
elasticsearch is sending a long along. ArrayAccessorNest.getValue()  
attempts to convert this into a Object and this is where it fails. The  
following sample Java program illustrates the same issue:

public class LongArrayToObjectArray {  
public static void main(String args) {  
Object O = (Object) (Object) new long[0];  
}  
}

Compile and run it and you'll see:

$ java LongArrayToObjectArray  
Exception in thread "main" java.lang.ClassCastException: [J cannot be cast  
to [Ljava.lang.Object;  
at LongArrayToObjectArray.main(LongArrayToObjectArray.java:5)

I'm not sure where the fix should live since I don't know where the long  
comes from, but presumably the calling code should pass Long or the MVEL  
compiler should be checking if the object is an array of primitive types,  
e.g.

if (obj instanceof long) {  
// ....  
} else if (obj instanceof int) {  
// ...  
} else if (...) {  
// ....  
} else if (obj instanceof Object) {  
// ....  
}

Kamil

On Wednesday, September 26, 2012 12:03:42 PM UTC-7, Kamil wrote:

> I'm trying to query some properties in a nested object with a script sort  
> and I'm running into some strange behaviour. I managed to contrive a small  
> example that reproduces this.
> 
> First, create a new index and apply the attached mapping:
> 
> curl -X PUT [http://localhost:9200/widgets](http://localhost:9200/widgets)  
> curl -X PUT [http://localhost:9200/widgets/widget/\_mapping](http://localhost:9200/widgets/widget/_mapping) -d @widget.json
> 
> Then add some objects to the index:
> 
> curl -X PUT [http://localhost:9200/widgets/widget/1](http://localhost:9200/widgets/widget/1) -d  
> '{"id":1,"type":"pegasus","components":[{"id":1,"type":"honda  
> civic"},{"id":2,"type":"mazda rx-8"}]}'  
> curl -X PUT [http://localhost:9200/widgets/widget/2](http://localhost:9200/widgets/widget/2) -d  
> '{"id":2,"type":"pegasus","components":[{"id":1,"type":"honda  
> accord"},{"id":2,"type":""}]}'  
> curl -X PUT [http://localhost:9200/widgets/widget/3](http://localhost:9200/widgets/widget/3) -d  
> '{"id":3,"type":"unicorn","components":[{"id":3,"type":"toyota supra"}]}'  
> curl -X PUT [http://localhost:9200/widgets/widget/4](http://localhost:9200/widgets/widget/4) -d  
> '{"id":4,"type":"unicorn","components":}'
> 
> I'm trying to find all widgets that have a component with "id" 1 and I  
> want to sort by the "type" value. Anything without that value should get  
> sorted to the bottom (I'm using 'Z' for that below, though in practice I  
> use character '\uffe0'). I use the following script:
> 
> ids = doc['components.id'];  
> if (ids.empty || ids.values.length == 0)  
> return 'Z';
> 
> types = doc['components.type'];  
> if (!ids.multiValued)  
> return types.value;
> 
> for (i = 0; i \< ids.values.length; i++)  
> if (ids.values[i] == 2)  
> return type.values[i];
> 
> return 'Z';
> 
> I'm running it with curl like so:
> 
> curl -X GET [http://localhost:9200/widgets/widget/\_search?pretty](http://localhost:9200/widgets/widget/_search?pretty) -d  
> '{"sort":{"\_script":{"script":"ids=doc['''components.id'''];if(ids.empty||ids.values.length==0)return  
> '''Z''';type=doc['''components.type'''];if(!ids.multiValued)return  
> type.value;for(i=0;i\<ids.values.length;i++)if(ids.values[i]==2)return  
> type.values[i];return '''Z''';","type":"string","order":"asc"}}}'
> 
> When I run this, some of the shards fail with a ClassCastException (full  
> stack trace attached):
> 
> Caused by: java.lang.ClassCastException: [J cannot be cast to [Ljava.lang.  
> Object;  
> at org.elasticsearch.common.mvel2.optimizers.impl.refl.nodes.  
> ArrayAccessorNest.getValue(ArrayAccessorNest.java:53)  
> at org.elasticsearch.common.mvel2.optimizers.impl.refl.nodes.  
> GetterAccessor.getValue(GetterAccessor.java:40)  
> ... 31 more
> 
> Any ideas about what I may be doing wrong or how I can fix this? Thanks.
> 
> Kamil

--

---

<div class="post-metadata">

**Author:** ![kamil\_2](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kamil\_2](https://discuss.elastic.co/u/kamil_2)\
**Post date:** [September 27, 2012, 4:13am UTC](https://discuss.elastic.co/t/classcastexception-when-querying-nested-properties/9163/3 "2012-09-27T04:13:01Z")

</div>

After some digging through the source I found that this change alleviates  
the problem:  
[https://github.com/kjiwa/elasticsearch/commit/569f86399b83184904682147c0a979a15542cfa0](https://github.com/kjiwa/elasticsearch/commit/569f86399b83184904682147c0a979a15542cfa0)

Not saying this is the correct solution but it does help. I assume the same  
will need to be applied for other fields that use double, boolean, etc.

Kamil

On Wednesday, September 26, 2012 4:22:51 PM UTC-7, Kamil wrote:

> My guess is that somewhere along the way through to the MVEL compiler  
> elasticsearch is sending a long along. ArrayAccessorNest.getValue()  
> attempts to convert this into a Object and this is where it fails. The  
> following sample Java program illustrates the same issue:
> 
> public class LongArrayToObjectArray {  
> public static void main(String args) {  
> Object O = (Object) (Object) new long[0];  
> }  
> }
> 
> Compile and run it and you'll see:
> 
> $ java LongArrayToObjectArray  
> Exception in thread "main" java.lang.ClassCastException: [J cannot be  
> cast to [Ljava.lang.Object;  
> at LongArrayToObjectArray.main(LongArrayToObjectArray.java:5)
> 
> I'm not sure where the fix should live since I don't know where the long  
> comes from, but presumably the calling code should pass Long or the MVEL  
> compiler should be checking if the object is an array of primitive types,  
> e.g.
> 
> if (obj instanceof long) {  
> // ....  
> } else if (obj instanceof int) {  
> // ...  
> } else if (...) {  
> // ....  
> } else if (obj instanceof Object) {  
> // ....  
> }
> 
> Kamil
> 
> On Wednesday, September 26, 2012 12:03:42 PM UTC-7, Kamil wrote:
> 
> > I'm trying to query some properties in a nested object with a script sort  
> > and I'm running into some strange behaviour. I managed to contrive a small  
> > example that reproduces this.
> > 
> > First, create a new index and apply the attached mapping:
> > 
> > curl -X PUT [http://localhost:9200/widgets](http://localhost:9200/widgets)  
> > curl -X PUT [http://localhost:9200/widgets/widget/\_mapping](http://localhost:9200/widgets/widget/_mapping) -d @widget.json
> > 
> > Then add some objects to the index:
> > 
> > curl -X PUT [http://localhost:9200/widgets/widget/1](http://localhost:9200/widgets/widget/1) -d  
> > '{"id":1,"type":"pegasus","components":[{"id":1,"type":"honda  
> > civic"},{"id":2,"type":"mazda rx-8"}]}'  
> > curl -X PUT [http://localhost:9200/widgets/widget/2](http://localhost:9200/widgets/widget/2) -d  
> > '{"id":2,"type":"pegasus","components":[{"id":1,"type":"honda  
> > accord"},{"id":2,"type":""}]}'  
> > curl -X PUT [http://localhost:9200/widgets/widget/3](http://localhost:9200/widgets/widget/3) -d  
> > '{"id":3,"type":"unicorn","components":[{"id":3,"type":"toyota supra"}]}'  
> > curl -X PUT [http://localhost:9200/widgets/widget/4](http://localhost:9200/widgets/widget/4) -d  
> > '{"id":4,"type":"unicorn","components":}'
> > 
> > I'm trying to find all widgets that have a component with "id" 1 and I  
> > want to sort by the "type" value. Anything without that value should get  
> > sorted to the bottom (I'm using 'Z' for that below, though in practice I  
> > use character '\uffe0'). I use the following script:
> > 
> > ids = doc['components.id'];  
> > if (ids.empty || ids.values.length == 0)  
> > return 'Z';
> > 
> > types = doc['components.type'];  
> > if (!ids.multiValued)  
> > return types.value;
> > 
> > for (i = 0; i \< ids.values.length; i++)  
> > if (ids.values[i] == 2)  
> > return type.values[i];
> > 
> > return 'Z';
> > 
> > I'm running it with curl like so:
> > 
> > curl -X GET [http://localhost:9200/widgets/widget/\_search?pretty](http://localhost:9200/widgets/widget/_search?pretty) -d  
> > '{"sort":{"\_script":{"script":"ids=doc['''components.id'''];if(ids.empty||ids.values.length==0)return  
> > '''Z''';type=doc['''components.type'''];if(!ids.multiValued)return  
> > type.value;for(i=0;i\<ids.values.length;i++)if(ids.values[i]==2)return  
> > type.values[i];return '''Z''';","type":"string","order":"asc"}}}'
> > 
> > When I run this, some of the shards fail with a ClassCastException (full  
> > stack trace attached):
> > 
> > Caused by: java.lang.ClassCastException: [J cannot be cast to [Ljava.lang  
> > .Object;  
> > at org.elasticsearch.common.mvel2.optimizers.impl.refl.nodes.  
> > ArrayAccessorNest.getValue(ArrayAccessorNest.java:53)  
> > at org.elasticsearch.common.mvel2.optimizers.impl.refl.nodes.  
> > GetterAccessor.getValue(GetterAccessor.java:40)  
> > ... 31 more
> > 
> > Any ideas about what I may be doing wrong or how I can fix this? Thanks.
> > 
> > Kamil

--

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 6, 2017, 3:11am UTC](https://discuss.elastic.co/t/classcastexception-when-querying-nested-properties/9163/4 "2017-07-06T03:11:14Z")

</div>


