Skip to content

Instantly share code, notes, and snippets.

@neumino
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neumino/47b6fc616d9e884757a5 to your computer and use it in GitHub Desktop.
Save neumino/47b6fc616d9e884757a5 to your computer and use it in GitHub Desktop.

Here's a proposal:

join takes 2 arguments:

  • left_key that can be a string or a function (it's the same thing as what eqJoin require for the first argument
  • other_table: the second sequence is a table.

The command has the following options:

  • index - <string>: The name of the index used on other_table to perform the join, default to the primary key.
  • group - <string>: If this option is undefined, the join command would operate as it does now. If it's set to a string, it would group the right values into an array and inject in the field (or just inject the document is unique is set to true (the value for group). The default is undefined.
  • outer_join - <boolean> whether the join should behave like an outer join or not. By default true. The value is always false when group is false. Edge case: the joined value should be an empty array, or null if no document can be joined.
  • multi - <boolean>: if set to true, the join is performed on each value of the left key (supposing that the left key maps to an array). Default to false. If the value is not an array, the join should not be performed:
  • unique - <boolean>: If more than one document is found, we should return an error.
  • compose - <function>: compose the joined sequence/object with a method. The function provides takes one argument which is the sequence/object returned by the join operation.
  • overwrite - <boolean> replace the document with the joined one.

Examples:

  • Simple join:
r.table("posts").join("id", r.table("comments"), {index: "postId", group: "comments"}
// equivalent to
r.table("posts").merge(function(post) {
    return post.merge({
        comments: r.table("comments").getAll(post("id"), {index: "postId"}).coerceTo("ARRAY")
    })
})
  • With outerJoin: false
r.table("posts").join("id", r.table("comments"), {index: "postId", group: "comments", outerJoin: false}
// equivalent to
r.table("posts").concatMap(function(post) {
    return r.table("comments").getAll(post("id"), {index: "postId"}).coerceTo("ARRAY").do(function(sequence) {
        r.branch(
            sequence.isEmpty(),
            [],
            [post.merge({ comments: sequence })]
        )
    })
})
  • Compose a joined sequence with an orderBy
r.table("posts").join("id", r.table("comments"), {
    index: "postId",
    group: "comments",
    compose: function(sequence) {
        return sequence.orderBy("date")
    }
}
// equivalent to
r.table("posts").merge(function(post) {
    return post.merge({
        comments: r.table("comments").getAll(post("id"), {index: "postId"})
            .orderBy("date").coerceTo("ARRAY") // the coerce here is optional
    })
})
  • Nested joins
r.table("posts").join("id", r.table("comments"), {
    index: "postId",
    group: "comments",
    compose: function(sequence) {
        return sequence.join("authorId", r.table("author"), {unique: true, group: "author"}
    }
}
// equivalent to
r.table("posts").merge(function(post) {
    return post.merge({
        comments: r.table("comments").getAll(post("id"), {index: "postId"})
            .merge(function(comment) {
               return { author: r.table("author").get(comment("authorId") }
            }).coerceTo("ARRAY") // the coerce here is optional
    })
})
  • Nested joined on a non primary key
r.table("posts").join("id", r.table("comments"), {
    index: "postId",
    group: "comments",
    compose: function(sequence) {
        return sequence.join("authorId", r.table("author"), {unique: true, group: "author", index: "uniqueId"}
    }
}
// equivalent to
r.table("posts").merge(function(post) {
    return post.merge({
        comments: r.table("comments").getAll(post("id"), {index: "postId"})
            .merge(function(comment) {
                 return { 
                    author: r.do(
                        r.table("author").getAll(comment("authorId") , {index: "uniqueId"}).coerceTo("ARRAY"),
                        function(sequence) {
                            r.branch(
                                sequence.count().gt(1),
                                r.error("More than one document found")
                                sequence.nth(0).default(null)
                            )
                        })
                 }
            }).coerceTo("ARRAY") // the coerce here is optional
    })
})
  • Many to many relations where the link between two documents is not returned.
r.table("students").join("id", r.table("student_class"), {
    index: "studentId",
    group: "classes",
    compose: function(sequence) {
        return sequence.join("classId", r.table("class"), {unique: true, overwrite: true}
    }
}
// equivalent to
r.table("students").merge(function(student) {
    return {
        classes: r.table("student_class").getAll(student("id"), {index: "studentId"}).map(function(link) {
            return r.table("class").get(link("classId"))
        })
    }
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment