Hi, I need to represent this
PUT my_index/animal/4444
{
"name": "Arara",
"location": "Brasil",
"colors": ["Yellow", "Green", "Blue"]
}
The above works nice and I can perform matches on colors
GET /myindexer/animal/_search
{
"query": {
"bool": {
"must": [
{"match": {
"colors": "Blue"
}}
]
}
}
}
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.5,
"hits": [
{
"_index": "my_index",
"_type": "animal",
"_id": "4444",
"_score": 0.5,
"_source": {
"name": "Arara",
"location": "Brasil",
"colors": [
"Yellow",
"Green",
"Blue"
]
}
}
]
}
}
So to represent the _colors_ list how can I do, is there a _List_ or _Array_ type?
class Animal(DocType):
name = String()
location = String()
colors = List(String()) (????)
If the following is ok (from docs)
assign some field values, can be values or lists of values
colors = String(fields={'raw': String(index='not_analyzed')})
Should I implement String field using those parameters? or a simple String() can support a list of values?
If so, is not better to have a explicit List() type?
The way I understand it, anything can be a list of objects.
So, you just have to make sure that your initialization of the attribute makes it a list, even if there is only one element in it:
>>> a = Animal(name="Dog", colors=["brown"])
>>> a.to_dict()
{"name": "Dog", "colors": ["brown"]}
Adding the fields= {'raw': String(index='not_analyzed')} has nothing to do with making the attribute a list or not. Is has to do with indexing.
If you have:
colors = String(fields={'raw': String(index='not_analyzed')})
Then you can search either colors, which will be an analyzed field, or you can search colors.raw, which will look for exact values.
For example, a search in color for "blue" will find "blue" of course, but also "light blue" and "dark blue". Whereas a search in color.raw for "blue" will only find "blue".
Thanks for the explanation @njoannin
Maybe it is a good idea to implement a List() field?
I want to implement a switch to make a field a list by default. It will be available for all the fields. It was described in #83
@rochacbruno You're welcome!
@HonzaKral I'd forgotten that suggestion you made of adding a switch. Looking forward to it :)
I still don't get how to implement a list field I used the type Keyword as a work arround but that's not the right impelementation
@abdelwahebmoalla you don't need to explicitly define a field as a list, just assign a list of values to it and it will work. if you want the default value of that field to be a list just specify multi=True when instantiating the field on your Document subclass:
from elasticsearch_dsl import Document, Keyword, Text
class BlogPost(Document):
title = Text()
content = Text()
tags = Keyword(multi=True)
BlogPost.init()
bp = BlogPost()
bp.tags.append('tag1')
bp.save()
Hope this helps!
Most helpful comment
@abdelwahebmoalla you don't need to explicitly define a field as a list, just assign a list of values to it and it will work. if you want the default value of that field to be a list just specify
multi=Truewhen instantiating the field on yourDocumentsubclass:Hope this helps!