Search code examples
mysqlsqljoinrethinkdbnosql

gorethink inner join


I don't quit understand joins in RethinkDB and unfortunately there is very little documentation about it in German.

So i have a table 'categories' and there i have two docs:

{"id":1, "title":"Category 1"}
{"id":2, "title":"Category 2"}

Than i have a second table 'forums' and there i have three docs:

{"id":1, "title":"Forum 1", "categoryId":1}
{"id":2, "title":"Forum 2", "categoryId":1}
{"id":3, "title":"Forum 3", "categoryId":2}

What i want as an result is:

[{"id":1, "title":"Category 1", "forums":[{"id":1, "title":"Forum 1"},{"id":2, "title":"Forum 2"}]}, {"id":2, "title":"Category 2", "forums":[{"id":3, "title":"Forum 3"}]}]

I can't figure out how I can translate this JavaScript example (https://www.rethinkdb.com/api/javascript/#inner_join) to Go, since the arguments (marvelRow, dcRow) in the function need declarations in Go, but I have no idea which.


Solution

  • Let's first write it in JavaScript, then we will do it in Go, so you know how to do it next time.

    What you want can easily do with either join or mapping. However, join will return a paird of match document, not in the nested way as you want. We can however map it like this:

    r.table('categories')
      .merge(function(cat) {
        return {
          forums: r.table('forums').filter({categoryId: cat('id')}).without('categoryId').coerceTo('array')
        }
      })
    

    Now let's move to Go lang.

    package main
    
    import (
        r "github.com/dancannon/gorethink"
        "log"
    )
    
    func main() {
    
        s, _ := r.Connect(r.ConnectOpts{
            Address:  "127.0.0.1:28015",
            Database: "test",
            MaxIdle:  10,
            MaxOpen:  10,
        })
    
    
        res, err := r.DB("test").Table("categories").Merge(func(doc r.Term) interface{} {
            return map[string]interface{}{
                "forums": r.DB("test").Table("forums").Filter(map[string]interface{}{
                    "categoryId": doc.Field("id"),
                }).CoerceTo("array"),
            }
        }).Run(s)
    
        log.Println(err)
    
        var row interface{}
        for res.Next(&row) {
            log.Println(row)
        }
    }
    

    Everything is almost identical, except that in Go lang, you have to specified type. So you convert JS anonoymous function into Go lang anonymous function, but now everything will have type of r.Term most of time. You also have to specify return type, as we use interface in our case. JavaScript object becomes map[string]interface{} now.

    In general, just go to this page https://github.com/dancannon/gorethink/wiki/Go-ReQL-command-reference and started to convert the JS one step at a time. It's almost one-one mapping except the type.