7

I started using the python library elasticsearch-dsl.

I am trying to implement a parent-child relationship but it is not working:

    class Location(DocType):
        name = String(analyzer='snowball', fields={'raw': String(index='not_analyzed')})
        latitude = String(analyzer='snowball')
        longitude = String(analyzer='snowball')
        created_at = Date()

   class Building(DocType):
       parent = Location()
Kamil Sindi
  • 16,733
  • 15
  • 85
  • 113
Renjith
  • 516
  • 1
  • 6
  • 25
  • 1
    Code example? Actual problem? – scooter me fecit Jan 28 '16 at 18:18
  • @ScottM updated the code sample – Renjith Jan 29 '16 at 18:58
  • There are a lot of different options to implementing object relations in the relational database sense. You could decide to embed documents-within-documents (basically, a sub-table within a table, if you will.) Or reimplement a relational database "join" primitive. Would help if you explained the approach(es) you're considering, technical challenges encountered, etc. Your quesiton is too broad for anyone to give you a specific answer. – scooter me fecit Feb 01 '16 at 19:25

2 Answers2

10

elasticsearch-dsl has parent-child relationship built in using MetaField:

class Location(DocType):
    name = String(analyzer='snowball', fields={'raw': String(index='not_analyzed')})
    latitude = String(analyzer='snowball')
    longitude = String(analyzer='snowball')
    created = Date()

    class Meta:
        doc_type = 'location' 

class Building(DocType):

    class Meta:
        doc_type = 'building'
        parent = MetaField(type='location')

How to insert and query (HT to @Maresh):
- DSL get: ChildDoc.get(id=child_id, routing=parent_id)
- DSL insert: I believe it's child.save(id=child_id, routing=parent_id)
- Dictionary insert: specify '_parent': parent_id in dictionary

Kamil Sindi
  • 16,733
  • 15
  • 85
  • 113
  • 1
    Do you happen to know how to test the parent_id when saving the child, I'm struggling with this. – Maresh Mar 29 '16 at 13:52
  • 1
    @Maresh to insert you specify a `_parent` key in the dictionary. For search you do `MyDoc.get(id=doc_id, routing=parent_id)`. – Kamil Sindi Mar 29 '16 at 14:13
  • 1
    So when I save the child is do: child.save(parent=parent.meta.id) ? Thanks man. Edit your answer with that, it's quite useful and the doc does not say anything about that. – Maresh Mar 29 '16 at 14:16
  • 1
    @Maresh I believe it's `child.save(id=child_id, routing=parent_id)`. Can you check? – Kamil Sindi Mar 29 '16 at 14:24
  • 1
    Confirmed. Thanks a lot. – Maresh Mar 29 '16 at 14:35
  • @Maresh How does one get the parent from getting the child? What does the search query look like? – user805981 Mar 31 '16 at 12:53
  • Hmm I'm not totalky sure, I use ES as document store for this one. But you'll have a _parent with the Metadata I believe, there are some example in the ES doc. – Maresh Mar 31 '16 at 13:35
  • 1
    When you say document store... you mean you treating the document store as if a relational database with a foreign key which is basically `routing`? – user805981 Mar 31 '16 at 20:16
  • How can we form the has child query with Elasticsearch DSL in python – devanathan Oct 05 '16 at 04:36
  • UPDATE: No longer works in ElasticSearch 6. Must use `Join` field instead. – andy Jan 18 '18 at 23:24
1

OK, thanks all. The simple and messy solution that worked for me was to use:

from elasticsearch_dsl import Mapping

mcc = Mapping(typeChild)
mcc.meta('_parent', type=typeParent)
mcc.field(fieldName, 'string', fielddata=True, store=True)
mcc.save(index)

BEFORE creating the parent doc-type

Ori5678
  • 347
  • 1
  • 4
  • 11