Reputation: 515
I needed some help with a query that I trying to execute.
I have a field called scores inside one of my indexes which stores some ai model scores for as a json
. The basic structure of this field is like (showing a couple of records from the index):
[{"scores":
{"a/b": 1.231,
"a/c": 23.11,
"x/a": 1232.1}},
{"scores":
{"a/d": 3.1}}]
And the mapping is something like:
{"scores":
{"properties":
{"a/b": {"type":"float"},
"a/c": {"type":"float"},
"a/d": {"type":"float"}}}}
The value for the field scores, which is another json
will have arbitrary fields i.e. I won't know which fields are present in that json
beforehand.
What I want to do is to search for the keys inside that json
i.e. if I search for a/
, it should return ["a/b", "a/d", "a/c"].
I know this is possible via nested query, but looks like for that I'll need to re-map my indexes, so that the field scores has a flatter data structure. However I didn't want to do that for now and just wanted to use the existing structure and execute my query.
If anyone has ideas about this, kindly throw them my way.
Upvotes: 0
Views: 715
Reputation: 16895
You can use _source
to limit what's retrieved:
POST indexname/_search
{
"_source": "scores.a/*"
}
Alternatively, you could employ script_fields
which do exactly the same but offer playroom for value modification too:
POST indexname/_search
{
"script_fields": {
"scores_prefixed_with_a": {
"script": {
"source": """params._source.scores.entrySet()
.stream()
.filter(e->e.getKey().startsWith(params.prefix))
.collect(Collectors.toMap(e->e.getKey(),e->e.getValue()))""",
"params": {
"prefix": "a/"
}
}
}
}
}
Upvotes: 1
Reputation: 43904
Use .filter()
- .reduce()
on Object.keys()
const data = [{"scores": {"a/b": 1.231, "a/c": 23.11, "x/a": 1232.1}}, {"scores": {"a/d": 3.1}}];
const allowed = 'a/';
const res = data.map((d) =>
Object.keys(d.scores)
.filter(key => key.startsWith(allowed)))
.reduce((prev, curr) => prev.concat(curr));
console.log(res)
[
"a/b",
"a/c",
"a/d"
]
const data = [{"scores": {"a/b": 1.231, "a/c": 23.11, "x/a": 1232.1}}, {"scores": {"a/d": 3.1}}];
const allowed = 'a/';
const res = data.map((d) =>
Object.keys(d.scores)
.filter(key => key.startsWith(allowed))
.reduce((obj, key) => { obj[key] = d.scores[key]; return obj; }, {}));
console.log(res);
Upvotes: 0