I want to modify scoring in ElasticSearch (v2+) based on the weight of a field in a nested object within an array.
For instance, using this data:
PUT index/test/0
{
"name": "red bell pepper",
"words": [
{"text": "pepper", "weight": 20},
{"text": "bell","weight": 10},
{"text": "red","weight": 5}
]
}
PUT index/test/1
{
"name": "hot red pepper",
"words": [
{"text": "pepper", "weight": 15},
{"text": "hot","weight": 11},
{"text": "red","weight": 5}
]
}
I want a query like {"words.text": "red pepper"} which would rank "red bell pepper" above "hot red pepper".
The way I am thinking about this problem is "first match the 'text' field, then modify scoring based on the 'weight' field". Unfortunately I don't know how to achieve this, if it's even possible, or if I have the right approach for something like this.
If proposing alternative approach, please try and keep a generalized idea where there are tons of different similar cases (eg: simply modifying the "red bell pepper" document score to be higher isn't really a suitable alternative).
The approach you have in mind is feasible. It can be achieved via function score in a nested query .
An example implementation is shown below :
PUT test
PUT test/test/_mapping
{
"properties": {
"name": {
"type": "string"
},
"words": {
"type": "nested",
"properties": {
"text": {
"type": "string"
},
"weight": {
"type": "long"
}
}
}
}
}
PUT test/test/0
{
"name": "red bell pepper",
"words": [
{"text": "pepper", "weight": 20},
{"text": "bell","weight": 10},
{"text": "red","weight": 5}
]
}
PUT test/test/1
{
"name": "hot red pepper",
"words": [
{"text": "pepper", "weight": 15},
{"text": "hot","weight": 11},
{"text": "red","weight": 5}
]
}
post test/_search
{
"query": {
"bool": {
"disable_coord": true,
"must": [
{
"match": {
"name": "red pepper"
}
}
],
"should": [
{
"nested": {
"path": "words",
"query": {
"function_score": {
"functions": [
{
"field_value_factor": {
"field" : "words.weight",
"missing": 0
}
}
],
"query": {
"match": {
"words.text": "red pepper"
}
},
"score_mode": "sum",
"boost_mode": "replace"
}
},
"score_mode": "total"
}
}
]
}
}
}
Result :
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "0",
"_score": 26.030865,
"_source": {
"name": "red bell pepper",
"words": [
{
"text": "pepper",
"weight": 20
},
{
"text": "bell",
"weight": 10
},
{
"text": "red",
"weight": 5
}
]
}
},
{
"_index": "test",
"_type": "test",
"_id": "1",
"_score": 21.030865,
"_source": {
"name": "hot red pepper",
"words": [
{
"text": "pepper",
"weight": 15
},
{
"text": "hot",
"weight": 11
},
{
"text": "red",
"weight": 5
}
]
}
}
]
}
The query in a nutshell would score a document that satisfies the must clause as follows : sum up the weights of the matched nested documents with the score of the must clause.
Related
For the store API endpoint /store-api/product is it possible to filter on the properties of a product? Not the defaults such as whether it's active or stock levels, but the properties we've defined on the product, for example colour or farbe? For the search endpoint it supports passing in a list of properties ID's which this one does not.
None of the below queries work, and return the various errors below or Call to a member function buildAccessor() on null.
{
"limit": 40,
"filter": [
{
"type": "contains",
"field": "Farbe",
"value": "red"
}
]
}
"Field \"Farbe\" in entity \"product\" was not found."
{
"limit": 40,
"filter": [
{
"type": "contains",
"field": "properties.Farbe",
"value": "red"
}
]
}
"Field \"Farbe\" in entity \"property_group_option\" was not found."
You can combine filters for the name of the property value and their respective group in a multi filter. The following example will only give you products that have the "shoe-color" property with the value "coral".
{
"limit": 1,
"includes": {
"product": ["id", "productNumber", "properties"],
"property_group_option": ["name", "group"],
"property_group": ["name"]
},
"associations": {
"properties": {
"associations": {
"group": []
}
}
},
"filter": [
{
"type": "multi",
"operator": "and",
"queries": [
{
"type": "equals",
"field": "properties.group.name",
"value": "shoe-color"
},
{
"type": "equals",
"field": "properties.name",
"value": "coral"
}
]
}
]
}
Example response:
{
"entity": "product",
"total": 1,
"aggregations": [],
"page": 1,
"limit": 1,
"elements": [
{
"productNumber": "6bbfe1f608504c9b9a7bf92d6a071734",
"properties": [
{
"name": "coral",
"group": {
"name": "shoe-color",
"apiAlias": "property_group"
},
"apiAlias": "property_group_option"
},
{
"name": "cotton",
"group": {
"name": "textile",
"apiAlias": "property_group"
},
"apiAlias": "property_group_option"
}
],
"id": "062ba988aa1840fa84371c9c43b2f838",
"apiAlias": "product"
}
],
"states": [],
"apiAlias": "dal_entity_search_result"
}
I'm working with LUIS and want to manage and deal not only with the top scoring intent but also with all others. In this specific situation occurs when someone inquires about two things in the same phrase.
For example: "I want to buy apples" ("Buy" intent) and "I want to sell bananas" ("Sell" intent) versus "I want to buy bananas and sell apples" ("buy" and "sell" intents on the same utterance).
The idea is to define a threshold that will accept as "valid" any intentions score above this confidence number.
During some tests I found out this can work if we have very few intents on the same utterance.
However if we increase the number of intents on the same utterance the results degrades very fast.
I included some examples to clarify what I mean: The output examples below were generated on a LUIS with 4 intents ("buy", "sell", "none" and "prank") and 1 entity ("fruit")
I want to buy apples ==>
{
"query": "i want to buy apples",
"topScoringIntent": {
"intent": "Buy",
"score": 0.999846
},
"intents": [
{
"intent": "Buy",
"score": 0.999846
},
{
"intent": "None",
"score": 0.2572831
},
{
"intent": "sell",
"score": 2.32163586e-7
},
{
"intent": "prank",
"score": 2.32163146e-7
}
],
"entities": [
{
"entity": "apples",
"type": "Fruit",
"startIndex": 14,
"endIndex": 19,
"resolution": {
"values": [
"apple"
]
}
}
]
}
I want to sell bananas ==>
{
"query": "i want to sell bananas",
"topScoringIntent": {
"intent": "sell",
"score": 0.999886036
},
"intents": [
{
"intent": "sell",
"score": 0.999886036
},
{
"intent": "None",
"score": 0.253938943
},
{
"intent": "Buy",
"score": 2.71893583e-7
},
{
"intent": "prank",
"score": 1.97906232e-7
}
],
"entities": [
{
"entity": "bananas",
"type": "Fruit",
"startIndex": 15,
"endIndex": 21,
"resolution": {
"values": [
"banana"
]
}
}
]
}
I want to eat a pizza ==>
{
"query": "i want to eat a pizza",
"topScoringIntent": {
"intent": "prank",
"score": 0.997353
},
"intents": [
{
"intent": "prank",
"score": 0.997353
},
{
"intent": "None",
"score": 0.378299
},
{
"intent": "sell",
"score": 2.72957237e-7
},
{
"intent": "Buy",
"score": 1.54754474e-7
}
],
"entities": []
}
Now with two intents... The score of each one starts to reduce aggressively
I want to buy apples and sell bananas ==>
{
"query": "i want to buy apples and sell bananas",
"topScoringIntent": {
"intent": "sell",
"score": 0.4442593
},
"intents": [
{
"intent": "sell",
"score": 0.4442593
},
{
"intent": "Buy",
"score": 0.263670564
},
{
"intent": "None",
"score": 0.161728472
},
{
"intent": "prank",
"score": 5.190861e-9
}
],
"entities": [
{
"entity": "apples",
"type": "Fruit",
"startIndex": 14,
"endIndex": 19,
"resolution": {
"values": [
"apple"
]
}
},
{
"entity": "bananas",
"type": "Fruit",
"startIndex": 30,
"endIndex": 36,
"resolution": {
"values": [
"banana"
]
}
}
]
}
and if we include the third intent, LUIS seems to collapse:
I want to buy apples, sell bananas and eat a pizza ==>
{
"query": "i want to buy apples, sell bananas and eat a pizza",
"topScoringIntent": {
"intent": "None",
"score": 0.139652014
},
"intents": [
{
"intent": "None",
"score": 0.139652014
},
{
"intent": "Buy",
"score": 0.008631414
},
{
"intent": "sell",
"score": 0.005520768
},
{
"intent": "prank",
"score": 0.0000210663875
}
],
"entities": [
{
"entity": "apples",
"type": "Fruit",
"startIndex": 14,
"endIndex": 19,
"resolution": {
"values": [
"apple"
]
}
},
{
"entity": "bananas",
"type": "Fruit",
"startIndex": 27,
"endIndex": 33,
"resolution": {
"values": [
"banana"
]
}
}
]
}
Do you know/recommend any approach that I should use to train LUIS in order to mitigate this issue? Dealing with multiple intents in the same utterance is key to my case.
Thanks a lot for any help.
You will likely need to do some pre-processing of the input using NLP to chunk the sentences and then train/submit the chunks one at a time. I doubt that LUIS is sophisticated enough to handle multiple intents in compound sentences.
Here's a sample code for preprocessing using Spacy in Python - have not tested this for more complicated sentences but this should work for your example sentence. You can use the segments below to feed to LUIS.
Multiple intents are not an easy problem to address and there may be other ways to handle them
import spacy
model = 'en'
nlp = spacy.load(model)
print("Loaded model '%s'" % model)
doc = nlp("i want to buy apples, sell bananas and eat a pizza ")
for word in doc:
if word.dep_ in ('dobj'):
subtree_span = doc[word.left_edge.i : word.right_edge.i + 1]
print(subtree_span.root.head.text + ' ' + subtree_span.text)
print(subtree_span.text, '|', subtree_span.root.head.text)
print()
If you know the permutations you are expecting you might be able to get the information you need.
I defined a single "buy and sell" intent, in addition to the individual buy and sell intents. I created two entities "Buy Fruit" and "Sell Fruit", each of which contained the "Fruit" entity from your example. Then in the "buy and sell" intent I used sample utterances like "I want to by apples and sell bananas", as well as switching the buy/sell around. I marked the fruit as a "fruit" entity, and the phrases as "buy fruit" and "sell fruit" as respectively.
This is the kind of output I get from "I want to buy a banana and sell an apple":
{
"query": "I want to buy a banana and sell an apple",
"prediction": {
"topIntent": "buy and sell",
"intents": {
"buy and sell": {
"score": 0.899272561
},
"Buy": {
"score": 0.06608531
},
"Sell": {
"score": 0.03477564
},
"None": {
"score": 0.009155964
}
},
"entities": {
"Buy Fruit": [
{}
],
"Sell Fruit": [
{}
],
"Fruit": [
"banana",
"apple"
],
"keyPhrase": [
"banana",
"apple"
],
"$instance": {
"Buy Fruit": [
{
"type": "Buy Fruit",
"text": "buy a banana",
"startIndex": 10,
"length": 12,
"score": 0.95040834,
"modelTypeId": 1,
"modelType": "Entity Extractor",
"recognitionSources": [
"model"
]
}
],
"Sell Fruit": [
{
"type": "Sell Fruit",
"text": "sell an apple",
"startIndex": 27,
"length": 13,
"score": 0.7225706,
"modelTypeId": 1,
"modelType": "Entity Extractor",
"recognitionSources": [
"model"
]
}
],
"Fruit": [
{
"type": "Fruit",
"text": "banana",
"startIndex": 16,
"length": 6,
"score": 0.9982499,
"modelTypeId": 1,
"modelType": "Entity Extractor",
"recognitionSources": [
"model"
]
},
{
"type": "Fruit",
"text": "apple",
"startIndex": 35,
"length": 5,
"score": 0.98748064,
"modelTypeId": 1,
"modelType": "Entity Extractor",
"recognitionSources": [
"model"
]
}
],
"keyPhrase": [
{
"type": "builtin.keyPhrase",
"text": "banana",
"startIndex": 16,
"length": 6,
"modelTypeId": 2,
"modelType": "Prebuilt Entity Extractor",
"recognitionSources": [
"model"
]
},
{
"type": "builtin.keyPhrase",
"text": "apple",
"startIndex": 35,
"length": 5,
"modelTypeId": 2,
"modelType": "Prebuilt Entity Extractor",
"recognitionSources": [
"model"
]
}
]
}
}
}
}
To make this work you would have to cater for all the possible permutations, so this isn't strictly a solution to discerning multiple intents. It's more about defining a composite intent for each permutation of individual intents that you wanted to cater for. In many applications that would not be practical, but in your example it could get you a satisfactory result.
Say I have a product collection like this:
{
"_id": "5a74784a8145fa1368905373",
"name": "This is my first product",
"description": "This is the description of my first product",
"category": "34/73/80",
"condition": "New",
"images": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstproduct_image1.jpg"
},
...
],
"attributes": [
{
"name": "Material",
"value": "Synthetic"
},
...
],
"variation": {
"attributes": [
{
"name": "Color",
"values": ["Black", "White"]
},
{
"name": "Size",
"values": ["S", "M", "L"]
}
]
}
}
and a variation collection like this:
{
"_id": "5a748766f5eef50e10bc98a8",
"name": "color:black,size:s",
"productID": "5a74784a8145fa1368905373",
"condition": "New",
"price": 1000,
"sale": null,
"image": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstvariation_image1.jpg"
}
],
"attributes": [
{
"name": "Color",
"value": "Black"
},
{
"name": "Size",
"value": "S"
}
]
}
I want to keep the documents separate and for the purpose of easy browsing, searching and faceted search implementation, I want to fetch all the data in a single query but I don't want to do join in my application code.
I know it's achievable using a third collection called summary that might look like this:
{
"_id": "5a74875fa1368905373",
"name": "This is my first product",
"category": "34/73/80",
"condition": "New",
"price": 1000,
"sale": null,
"description": "This is the description of my first product",
"images": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstproduct_image1.jpg"
},
...
],
"attributes": [
{
"name": "Material",
"value": "Synthetic"
},
...
],
"variations": [
{
"condition": "New",
"price": 1000,
"sale": null,
"image": [
{
"length": 1000,
"width": 1000,
"src": "products/images/firstvariation_image.jpg"
}
],
"attributes": [
"color=black",
"size=s"
]
},
...
]
}
problem is, I don't know how to keep the summary collection in sync with the product and variation collection. I know it can be done using mongo-connector but i'm not sure how to implement it.
please help me, I'm still a beginner programmer.
you don't actually need to maintain a summary collection, its redundant to store product and variation summary in another collection
instead of you can use an aggregate pipeline $lookup to outer join product and variation using productID
aggregate pipeline
db.products.aggregate(
[
{
$lookup : {
from : "variation",
localField : "_id",
foreignField : "productID",
as : "variations"
}
}
]
).pretty()
Background: I've implemented a partial search on a name field by indexing the tokenized name (name field) as well as a trigram analyzed name (ngram field).
I've boosted the name field to have exact token matches bubble up to the top of the results.
Problem: I am trying to implement a query that limits the nGram matches to ones that only match some threshold (say 80%) of the query string. I understand that minimum_should_match seems to be what I am looking for, but my problem is forming the query to actually produce those results.
My exact token matches are boosted to the top but I still get every document that has a single matching trigram in the ngram field.
GIST: Index settings and mapping
Index Settings
{
"my_index": {
"settings": {
"index": {
"number_of_shards": "5",
"max_result_window": "30000",
"creation_date": "1475853851937",
"analysis": {
"filter": {
"ngram_filter": {
"type": "ngram",
"min_gram": "3",
"max_gram": "3"
}
},
"analyzer": {
"ngram_analyzer": {
"filter": [
"lowercase",
"ngram_filter"
],
"type": "custom",
"tokenizer": "standard"
}
}
},
"number_of_replicas": "1",
"uuid": "AuCjcP5sSb-m59bYrprFcw",
"version": {
"created": "2030599"
}
}
}
}
}
Index Mappings
{
"my_index": {
"mappings": {
"my_type": {
"properties": {
"acw": {
"type": "integer"
},
"pcg": {
"type": "integer"
},
"date": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"dob": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"id": {
"type": "string"
},
"name": {
"type": "string",
"boost": 10
},
"ngram": {
"type": "string",
"analyzer": "ngram_analyzer"
},
"bdk": {
"type": "integer"
},
"mmw": {
"type": "integer"
},
"mpi": {
"type": "integer"
},
"sex": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
Solution Attempts
[GIST: Query Attempts] unlinkifying due to 2 link limit :(
(https://gist.github.com/jordancardwell/2e690013666e7e1da6ef1acee314b4e6)
I tried a multi-match query, which gives me correct search results, but I haven't had luck omitting results for names that only match a single trigram (say "odo" trigram inside "theodophilus")
//this matches 'frodo' and sends results to the top, since `name` field is boosted
// but also matches 'theodore' and 'rodolpho'
{
"size":100,
"from":0,
"query":{
"multi_match":{
"query":"frodo",
"fields":[
"name",
"ngram"
],
"type":"best_fields"
}
}
}
.
//I then tried to throw in the `minimum_must_match` option
// hoping it would filter out large strings that only had one matching trigram for instance
{
"size":100,
"from":0,
"query":{
"multi_match":{
"query":"frodo",
"fields":[
"name",
"ngram"
],
"type":"best_fields",
"minimum_should_match": "90%",
}
}
}
I've tried playing around in sense, to manually produce the match queries that this produces to allow me to only apply minimum_must_match to the ngram field but can't seem to get the syntax right.
// I then tried to contruct a custom query to just return the `minimum_should_match`d results on the ngram field
// I started with a query produced by using bodybuilder to `and` and `or` my other search criteria together
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
//each separate field's criteria `must`/`and`ed together
{
"query": {
"bool": {
"filter": {
"bool": {
"should": [
//each critereon for a specific field `should`/`or`ed together
{
//my attempt at getting `ngram` field results..
// should theoretically only return when field
// contains nothing but matching ngrams
// (i.e. exact matches and other fluke matches)
"query": {
"match": {
"ngram": {
"query": "frodo",
"minimum_should_match": "100%"
}
}
}
}
//... other critereon to be `should`/`or`ed together
]
}
}
}
}
}
//... other criteria to be `must`/`and`ed together
]
}
}
}
}
}
Can anyone see what I'm doing wrong?
It seems like this should be fairly straightforward to accomplish, but I must be missing something obvious.
UPDATE
I ran a query with _explain=true (using sense UI) to try to understand my results.
I queried for a match on the ngram field for "frod" with minimum_should_match = 100%, yet I still get every record that matches at least one ngram.
(e.g. rodolpho even though it doesn't contain fro)
GIST: test query and results
note: cross-posted from [discuss.elastic.co]
will make a link later, can't post more than 2 yet : /
(https://discuss.elastic.co/t/ngram-partial-match-limiting-ngram-results-in-multiple-field-query/62526)
I used your settings and mappings to create an index. And you queries seem to be working fine for me. I would suggest doing an explain on one of the "unexpected" documents which is being returned and see why it is being matched and returned with other results.
Here is what I did:
Run the analyze api on your analyzer to see how the query will be split into tokens.
curl -XGET 'localhost:9200/my_index/_analyze' -d '
{
"analyzer" : "ngram_analyzer",
"text" : "frodo"
}'
frodo will be split into 3 tokens with your analyzer.
{
"tokens": [
{
"token": "fro",
"start_offset": 0,
"end_offset": 5,
"type": "word",
"position": 0
},
{
"token": "rod",
"start_offset": 0,
"end_offset": 5,
"type": "word",
"position": 0
},
{
"token": "odo",
"start_offset": 0,
"end_offset": 5,
"type": "word",
"position": 0
}
]
}
I indexed 3 documents for testing (only used ngrams field) . Here are the docs:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "2",
"_score": 1,
"_source": {
"ngram": "theodore"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1,
"_source": {
"ngram": "frodo"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "3",
"_score": 1,
"_source": {
"ngram": "rudolpho"
}
}
]
}
}
The first query you mentioned, it matches frodo and theodore, but not rudolpho like you mentioned - which makes sense, since rudolpho does not produce any trigrams which match trigrams from frodo
frodo -> fro, rod, odo
rudolpho -> rud, udo, dol, olp, lph, pho
Using your second query, I get back only frodo (None of the other two) .
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.53148466,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 0.53148466,
"_source": {
"ngram": "frodo"
}
}
]
}
}
I then ran an explain (localhost:9200/my_index/my_type/2/_explain) on other two docs (theodore and rudolpho) and I see this (I have clipped the response)
{
"_index": "my_index",
"_type": "my_type",
"_id": "2",
"matched": false,
"explanation": {
"value": 0,
"description": "Failure to meet condition(s) of required/prohibited clause(s)",
"details": [
{
"value": 0,
"description": "no match on required clause ((ngram:fro ngram:rod ngram:odo)~2)",
"details": [
The above is expected since atleast two out of three tokens from frodo should match.
The story: Given the example documents below and by extending them, is it possible to get the following ranking:
A search on "Cereals" results in the following ranking
Cornflakes
Rice Krispies
A search on "Rice" results in the following ranking
Basmati
Rice Krispies
The documents against the search is performed:
[{
name: "Cornflakes"
},
{
name: "Basmati"
},
{
name: "Rice Krispies"
}]
Of course, some of them does not even held the search term, so an option is to add an array of synonyms with a text value and weight with would help in computing the ranking:
[{
name: "Cornflakes",
synonyms: [
{t: 'Cereals', weight: 100},
{t: 'Sugar', weight: 100}]
},
{
name: "Basmati",
synonyms: [
{t: 'Cereals', weight: 1},
{t: 'Rice', weight: 1000}]
},
{
name: "Rice Krispies",
synonyms: [
{t: 'Cereals', weight: 10},
{t: 'Rice', weight: 1}]
}]
Is it the right approach?
What is the Elastic Search query for taking into account weighted synonyms?
I think "tags" would be a more appropriate name for the field than "synonyms".
You could use a nested type to store tags and use function score to combine the value of the tags.weight field (of the best matching tag if any) with the match score on the name field.
One such implementation could look as follows:
put test
put test/tag_doc/_mapping
{
"properties" : {
"tags" : {
"type" : "nested" ,
"properties": {
"t" : {"type" : "string"},
"weight" : {"type" : "double"}
}
}
}
}
put test/tag_doc/_bulk
{ "index" : { "_index" : "test", "_type" : "tag_doc", "_id":1} }
{"name": "Cornflakes","tags": [{"t": "Cereals", "weight":100},{"t": "Sugar", "weight": 100}]}
{ "index" : { "_index" : "test", "_type" : "tag_doc","_id":2} }
{ "name": "Basmati","tags": [{"t": "Cereals", "weight": 1},{"t": "Rice", "weight": 1000}]}
{ "index" : { "_index" : "test", "_type" : "tag_doc","_id":3} }
{ "name": "Rice Krispies", "tags": [{"t": "Cereals", "weight": 10},{"t": "Rice", "weight": 1}]}
post test/_search
{
"query": {
"dis_max": {
"queries": [
{
"match": {
"name": {
"query": "cereals",
"boost": 100
}
}
},
{
"nested": {
"path": "tags",
"query": {
"function_score": {
"functions": [
{
"field_value_factor": {
"field": "tags.weight"
}
}
],
"query": {
"match": {
"tags.t": "cereals"
}
},
"boost_mode": "replace",
"score_mode": "max"
}
},
"score_mode": "max"
}
}
]
}
}
}
Result :
"hits": {
"total": 3,
"max_score": 100,
"hits": [
{
"_index": "test",
"_type": "tag_doc",
"_id": "1",
"_score": 100,
"_source": {
"name": "Cornflakes",
"tags": [
{
"t": "Cereals",
"weight": 100
},
{
"t": "Sugar",
"weight": 100
}
]
}
},
{
"_index": "test",
"_type": "tag_doc",
"_id": "3",
"_score": 10,
"_source": {
"name": "Rice Krispies",
"tags": [
{
"t": "Cereals",
"weight": 10
},
{
"t": "Rice",
"weight": 1
}
]
}
},
{
"_index": "test",
"_type": "tag_doc",
"_id": "2",
"_score": 1,
"_source": {
"name": "Basmati",
"tags": [
{
"t": "Cereals",
"weight": 1
},
{
"t": "Rice",
"weight": 1000
}
]
}
}
]
}