Accessing Child Index data using Java Custom Score Script

I have been using custom score which required the data from a child
index from the matched parent. I cannot find a way to access the child data
from the Doc object or Source object in Java. The only way I can find to
access the child data is to use a NodeClient or TransportClient object,
which seems quite inefficent as the code is already running by
elasticsearch itself and on it's classpath. Is there a better way to access
the child data directly instead of using a transportClient like the code
shown below? (The child data is to keep track of user selection of the
parent data).

public double runAsDouble() {

String parentKey = doc().field("parentId").getStringValue();
String childKey = user + "_" + parentKey ;

//The TransportClient object with host and port# is created in the 

Constructor of the custom script

GetResponse resp = transportClient.prepareGet(INDEX, CHILD_TYPE, 

childKey).execute().actionGet();
long field = resp.getVersion();

if (field <= 0)
 return Double.valueOf(1.0);
else
 return Double.valueOf(field+1);

}

--

If you can wrap this data from a child into a number, you can do something
like this:

"custom_score": {
"query": {
"top_children": {
"query": {
"custom_score": {
"query": { ... },
"script": script1,
}
},
"score": "max"
}
},
"script": script2
}

So, script1 will wrap whatever information you can get from child and
pass it to script2 as _score. That might not be what you asked for, but
the next best thing I can think of is injecting NodeClient and using it to
lookup the data that you need.

Igor

On Tuesday, January 15, 2013 12:09:57 PM UTC-5, Amy Lau wrote:

I have been using custom score which required the data from a child
index from the matched parent. I cannot find a way to access the child data
from the Doc object or Source object in Java. The only way I can find to
access the child data is to use a NodeClient or TransportClient object,
which seems quite inefficent as the code is already running by
elasticsearch itself and on it's classpath. Is there a better way to access
the child data directly instead of using a transportClient like the code
shown below? (The child data is to keep track of user selection of the
parent data).

public double runAsDouble() {

String parentKey = doc().field("parentId").getStringValue();
String childKey = user + "_" + parentKey ;

//The TransportClient object with host and port# is created in the 

Constructor of the custom script

GetResponse resp = transportClient.prepareGet(INDEX, CHILD_TYPE, 

childKey).execute().actionGet();
long field = resp.getVersion();

if (field <= 0)
 return Double.valueOf(1.0);
else
 return Double.valueOf(field+1);

}

--

Thanks for the reply. However, what you suggest doesn't seem that different
than what I am doing to access child data, since script1 will still have to
access the data through either a NodeClient or a TransportClient. I think
if I can construct a TransportClient (or NodeClient) during elasticsearch
startup and just use that instead of keep creating instances in the custom
script constructor, that should be better...

Is there a way to create Custom startup script in java and run that somehow
in elasticsearch startup?

On Tuesday, January 15, 2013 5:49:57 PM UTC-5, Igor Motov wrote:

If you can wrap this data from a child into a number, you can do something
like this:

"custom_score": {
"query": {
"top_children": {
"query": {
"custom_score": {
"query": { ... },
"script": script1,
}
},
"score": "max"
}
},
"script": script2
}

So, script1 will wrap whatever information you can get from child and
pass it to script2 as _score. That might not be what you asked for, but
the next best thing I can think of is injecting NodeClient and using it to
lookup the data that you need.

Igor

--

Maybe I misunderstood your question. I think there is a difference since
script1 will be running on child documents, so it will be able to access
child data using document or field lookup.

You don't need to construct NodeClient or TransportClient during startup,
you can simply inject Node into you Script Factory and then pass it to the
script during it's creation. I think something like this should work:

public static class Factory implements NativeScriptFactory {
    private Node node;

    @Inject
    public Factory(Node node) {
        this.node = node;
    }

    @Override
    public ExecutableScript newScript(@Nullable Map<String, Object> 

params) {
Client client = node.client();
// Parse other parameters
return new MyScript(client, ... other parameters ... );
}
}

On Wednesday, January 16, 2013 11:02:37 AM UTC-5, Amy Lau wrote:

Thanks for the reply. However, what you suggest doesn't seem that
different than what I am doing to access child data, since script1 will
still have to access the data through either a NodeClient or a
TransportClient. I think if I can construct a TransportClient (or
NodeClient) during elasticsearch startup and just use that instead of keep
creating instances in the custom script constructor, that should be
better...

Is there a way to create Custom startup script in java and run
that somehow in elasticsearch startup?

On Tuesday, January 15, 2013 5:49:57 PM UTC-5, Igor Motov wrote:

If you can wrap this data from a child into a number, you can do
something like this:

"custom_score": {
"query": {
"top_children": {
"query": {
"custom_score": {
"query": { ... },
"script": script1,
}
},
"score": "max"
}
},
"script": script2
}

So, script1 will wrap whatever information you can get from child and
pass it to script2 as _score. That might not be what you asked for,
but the next best thing I can think of is injecting NodeClient and using it
to lookup the data that you need.

Igor

--

Thanks so much for the answer, Igor. I think the injected Node client
should work for me. I am going to try and see.

--