Reputation: 1983
I have a dataset with a field that contains a list of strings for each document. I'm looking for a query that will give me the list of unique strings in that field
I thought reduce might be what I'm looking for:
r.db('test').table('entity')('listField').reduce(function (left, right) {
var i;
var l;
for (i = 0, l = right.length; i < l; i ++) {
if (left.not().contains(right[i])) {
left.append(right[i]);
}
}
return left;
}).default([])
But this only returns the listField
of the first item in the list: ["C", "F", "G"]
. Any document in the table can have any number of an unknown list of values in listField
. How do I get the list of all available values?
Upvotes: 0
Views: 149
Reputation: 21115
You have to remember that client side scripts cannot work in RethinkDB: these are just two very different scopes. RethinkDB only requires you to supply a ReQL expression that can be evaluated on the server side. By a ReQL expression I mean the stuff that can be found in the JavaScript ReQL command reference, and not client-side statements of any kind (statements, assignments, loops, branching, etc). reduce
, similarly to all the rest of the terms, can accept a function that can build a new ReQL expression, and not meant to evaluate anything related to the query. In your case, the reduce
function returns the left
expression term (regardless your operations over the term -- they all create a new expression), and that's why you're getting your document listField
value. As a result, expression builder functions are invoked before the query is actually executed.
Since you just want to find a unique value, you can rewrite the query and easily use RethinkDB built-ins like concatMap
and distinct
(these operations are very basic not just in RethinkDB):
//r.db('test').table('entity').delete();
//r.db('test').table('entity').insert([{
// listField: ['A', 'B', 'B', 'C', 'C', 'C', 'C']
//}, {
// listField: ['B', 'C', 'A', 'Z', 'Z', 'Z']
//}]);
r.db('test')
.table('entity')
.concatMap(r.row('listField'))
.distinct();
And you'll obtain the result:
[
"A",
"B",
"C",
"Z"
]
The query above can be rewritten with an expression build function as well:
r.db('test')
.table('entity')
.concatMap(row => {
// your local stuff here that is executed before the query is sent to the server and executed
// note that this function must return a ReQL expression
return row.getField('listField');
})
.distinct();
Upvotes: 1