desc: Tests that manipulation data in tables table_variable_name: tbl tbl2 tbl3 tests: # Set up some data - py: tbl.insert([{'id':i, 'a':i%4} for i in xrange(100)]) js: | tbl.insert(function(){ var res = [] for (var i = 0; i < 100; i++) { res.push({id:i, 'a':i%4}); } return res; }()) rb: tbl.insert((0..99).map{ |i| { :id => i, :a => i % 4 } }) ot: {'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':100} - cd: tbl.index_create('a') ot: {'created':1} - py: tbl.index_create('truncated_a', lambda x: ['a' * 300, x['a']]) ot: {'created':1} - py: tbl.index_create('error_prone', lambda x: 1/x['a']) ot: {'created':1} - cd: tbl.index_wait().pluck('index', 'ready') - py: tbl2.insert([{'id':i, 'b':i%4} for i in xrange(100)]) js: | tbl2.insert(function(){ var res = [] for (var i = 0; i < 100; i++) { res.push({id:i, 'b':i%4}); } return res; }()) rb: tbl2.insert((0..99).map{ |i| { :id => i, :b => i % 4 } }) ot: {'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':100} - py: tbl3.insert([{'id':i, 'a':i%4, 'b':{'c':i%5}} for i in xrange(100)]) js: | tbl3.insert(function(){ var res = [] for (var i = 0; i < 100; i++) { res.push({id:i, 'a':i%4, 'b':{'c':i%5}}); } return res; }()) rb: tbl3.insert((0..99).map{ |i| { :id => i, :a => i % 4, :b => { :c => i % 5 } } }) ot: {'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':100} # Map-Reduce - py: - tbl.map(lambda row:row['id']).reduce(lambda a,b:a+b) - tbl.map(r.row['id']).reduce(lambda a,b:a+b) js: - tbl.map(function(row) { return row('id'); }).reduce(function(a,b) { return a.add(b); }) - tbl.map(r.row('id')).reduce(function(a,b) { return a.add(b); }) rb: tbl.map{ |row| row[:id] }.reduce{ |a, b| a + b } ot: 4950 # Map-Reduce - py: - tbl.union(tbl).map(lambda row:row['id']).reduce(lambda a,b:a+b) - tbl.union(tbl).map(r.row['id']).reduce(lambda a,b:a+b) js: - tbl.union(tbl).map(function(row) { return row('id'); }).reduce(function(a,b) { return a.add(b); }) - tbl.union(tbl).map(r.row('id')).reduce(function(a,b) { return a.add(b); }) rb: tbl.union(tbl).map{ |row| row[:id] }.reduce{ |a, b| a + b } ot: 9900 # Map-Reduce - py: - tbl.coerce_to("array").union(tbl).map(lambda row:row['id']).reduce(lambda a,b:a+b) - tbl.coerce_to("array").union(tbl).map(r.row['id']).reduce(lambda a,b:a+b) js: - tbl.coerce_to("array").union(tbl).map(function(row) { return row('id'); }).reduce(function(a,b) { return a.add(b); }) - tbl.coerce_to("array").union(tbl).map(r.row('id')).reduce(function(a,b) { return a.add(b); }) rb: tbl.coerce_to("array").union(tbl).map{ |row| row[:id] }.reduce{ |a, b| a + b } ot: 9900 # Map-Reduce - py: - tbl.union(tbl.coerce_to("array")).map(lambda row:row['id']).reduce(lambda a,b:a+b) - tbl.union(tbl.coerce_to("array")).map(r.row['id']).reduce(lambda a,b:a+b) js: - tbl.union(tbl.coerce_to("array")).map(function(row) { return row('id'); }).reduce(function(a,b) { return a.add(b); }) - tbl.union(tbl.coerce_to("array")).map(r.row('id')).reduce(function(a,b) { return a.add(b); }) rb: tbl.union(tbl.coerce_to("array")).map{ |row| row[:id] }.reduce{ |a, b| a + b } ot: 9900 # Empty stream test. - py: tbl.get_all().fold(0, lambda acc, _: acc.add(1), emit=lambda old,row,acc: [acc]) ot: [] - py: r.range(0, 10).fold(0, lambda acc, _: acc.add(1), emit=lambda old,row,acc: acc) ot: err("ReqlQueryLogicError", "Expected type ARRAY but found NUMBER.") - py: r.range(0, 10).fold(0, lambda acc, _: acc.add(1), emit=lambda old,row,acc: r.range()) ot: err("ReqlQueryLogicError", "Expected type DATUM but found SEQUENCE:") - py: r.range(0, 10).fold(0, lambda acc, _: acc.add(1), emit=lambda old,row,acc: [acc]).changes() ot: err("ReqlQueryLogicError", "Cannot call `changes` on an eager stream.") # Return array from final_emit - js: r.expr(["a"]).fold(null, function() {return null;}, {emit: function() {return [0]}, finalEmit: function() {return [1, 2, 3]} }) ot: [0, 1, 2, 3] # Concat-map - py: tbl.concat_map(lambda row:[]) js: tbl.concatMap(function(row) { return []; }) rb: tbl.concat_map{ |row| [] } ot: [] - def: py: ccm = tbl.concat_map(lambda row:[row['a'], (row['a'] + 1) % 4]) js: ccm = tbl.concatMap(function(row) { return [row('a'), row('a').add(1).mod(4)]; }) rb: ccm = tbl.concat_map{ |row| [row[:a], (row[:a] + 1) % 4] } - cd: ccm.count() ot: 200 - py: ccm.reduce(lambda a,b:(a+b) % 4) js: ccm.reduce(function(a,b) { return a.add(b).mod(4); }) rb: ccm.reduce{ |a, b| (a + b) % 4 } ot: 0 # Order by - py: tbl.order_by('id')[0] js: tbl.orderBy('id').nth(0) rb: tbl.order_by(:id)[0] ot: {'id':0, 'a':0} - py: tbl.order_by([1,2,3]) js: tbl.orderBy([1,2,3]) rb: tbl.order_by([1,2,3]) ot: err('ReqlQueryLogicError', 'Expected type STRING but found ARRAY.', [0]) - py: tbl.order_by(index='id')[0] js: tbl.orderBy({index:'id'}).nth(0) rb: tbl.order_by('a', :index => :id)[0] ot: {'id':0, 'a':0} - py: tbl.order_by(index='id')[0].update({'a':0})['unchanged'] js: tbl.orderBy({index:'id'}).nth(0).update({a:0})('unchanged') rb: tbl.order_by('a', :index => :id)[0].update({a:0})['unchanged'] ot: 1 - py: tbl.get_all(0).update({'a':0})['unchanged'] js: tbl.getAll(0).update({a:0})('unchanged') rb: tbl.get_all(0).update({a:0})['unchanged'] ot: 1 - py: tbl.order_by(index='id').order_by(index='id')[0] js: tbl.orderBy({index:'id'}).orderBy({index:'id'}).nth(0) rb: tbl.order_by(:index => :id).order_by(:index => :id)[0] ot: err('ReqlQueryLogicError', 'Cannot perform multiple indexed ORDER_BYs on the same table.', [0]) - py: tbl.order_by(index='id').order_by(index='id')[0] js: tbl.orderBy({index:'id'}).orderBy({index:'id'}).nth(0) rb: tbl.order_by(:index => :id).order_by(:index => :id)[0] ot: err('ReqlQueryLogicError', 'Cannot perform multiple indexed ORDER_BYs on the same table.', [0]) - py: tbl.order_by('id').order_by(index='id')[0] js: tbl.orderBy('id').orderBy({index:'id'}).nth(0) rb: tbl.order_by(:id).order_by(:index => :id)[0] ot: err('ReqlQueryLogicError', 'Indexed order_by can only be performed on a TABLE or TABLE_SLICE.', [0]) - py: tbl.order_by('id').order_by(index='a')[0] js: tbl.orderBy('id').orderBy({index:'a'}).nth(0) rb: tbl.order_by(:id).order_by(:index => :a)[0] ot: err('ReqlQueryLogicError', 'Indexed order_by can only be performed on a TABLE or TABLE_SLICE.', [0]) - py: tbl.between(5, r.maxval, index='id').order_by(index='id')[0] js: tbl.between(5, r.maxval, {index:'id'}).orderBy({index:'id'}).nth(0) rb: tbl.between(5, r.maxval, :index => :id).order_by('a', :index => :id)[0] ot: {'id':5, 'a':1} - py: tbl.order_by('a', index='id').between(5, r.maxval, index='id')[0] js: tbl.orderBy('a', {index:'id'}).between(5, r.maxval, {index:'id'}).nth(0) rb: tbl.order_by('a', :index => :id).between(5, r.maxval, :index => :id)[0] ot: err('ReqlQueryLogicError', 'Expected type TABLE_SLICE but found SELECTION:', [0]) - py: tbl.order_by(lambda x: x['id'])[0] js: tbl.orderBy(function (x) { return x('id'); }).nth(0) rb: tbl.order_by{|x| x[:id]}[0] ot: {'id':0, 'a':0} - cd: tbl.order_by('a', 'id').nth(0) ot: {'id':0,'a':0} - py: tbl.order_by('id', index='a').nth(0) js: tbl.orderBy('id', {index:'a'}).nth(0) rb: tbl.order_by('id', :index => :a).nth(0) ot: {'id':0,'a':0} - py: tbl.order_by('id', index='truncated_a').nth(0) ot: {'id':0,'a':0} - py: tbl.order_by('id', index='error_prone').nth(0) ot: {'id':3,'a':3} - py: tbl.order_by(lambda x: [x['a'], x['id']])[0] js: tbl.orderBy(function (x) { return [x('a'), x('id')]; }).nth(0) rb: tbl.order_by{|x| [x[:a], x[:id]]}[0] ot: {'id':0, 'a':0} - cd: tbl.order_by(r.desc('a'), r.asc('id')).nth(0) ot: {'id':3,'a':3} - py: tbl.order_by('id', index=r.desc('a')).nth(0) js: tbl.orderBy('id', {index:r.desc('a')}).nth(0) rb: tbl.order_by('id', :index => r.desc(:a)).nth(0) ot: {'id':3,'a':3} - py: tbl.order_by(r.desc(lambda x: x['a']), lambda x: x['id'])[0] js: tbl.orderBy(r.desc(function (x) { return x('a'); }), function (x) { return x('id'); }).nth(0) rb: tbl.order_by(r.desc{|x| x[:a]}, lambda {|x| x[:id]})[0] ot: {'id':3, 'a':3} - cd: tbl.order_by(r.asc('a'), r.desc('id')).nth(0) ot: {'id':96,'a':0} - py: tbl.order_by(r.desc('id'), index='a').nth(0) js: tbl.orderBy(r.desc('id'), {index:'a'}).nth(0) rb: tbl.order_by(r.desc('id'), :index => :a).nth(0) ot: {'id':96,'a':0} - cd: tbl.order_by('id').type_of() ot: 'SELECTION' - cd: tbl.order_by('missing').order_by('id').nth(0) ot: {'id':0, 'a':0} - py: tbl.order_by('missing').order_by(index='id').nth(0) js: tbl.order_by('missing').order_by({index:'id'}).nth(0) rb: tbl.order_by('missing').order_by(:index => :id).nth(0) ot: err('ReqlQueryLogicError', 'Indexed order_by can only be performed on a TABLE or TABLE_SLICE.', [0]) - cd: tbl.order_by('id', 'missing').nth(0) ot: {'id':0, 'a':0} - py: tbl.order_by('missing', index='id').nth(0) js: tbl.order_by('missing', {index:'id'}).nth(0) rb: tbl.order_by('missing', :index => :id).nth(0) ot: {'id':0, 'a':0} - py: tbl.order_by(r.desc('id')).coerce_to('ARRAY') == tbl.order_by(lambda x: 0 - x['id']).coerce_to('ARRAY') rb: tbl.order_by(r.desc('id')).coerce_to("ARRAY").eq(tbl.order_by{|x| 0 - x[:id]}.coerce_to("ARRAY")) js: tbl.order_by(r.desc('id')).coerce_to("ARRAY").eq(tbl.order_by(function (x) { return r.expr(0).sub(x('id')); }).coerce_to("ARRAY")) ot: true - py: tbl.order_by(index=r.desc('id')).coerce_to('ARRAY') == tbl.order_by(lambda x: 0 - x['id']).coerce_to('ARRAY') rb: tbl.order_by(:index => r.desc(:id)).coerce_to("ARRAY").eq(tbl.order_by{|x| 0 - x[:id]}.coerce_to("ARRAY")) js: tbl.order_by({index:r.desc('id')}).coerce_to("ARRAY").eq(tbl.order_by(function (x) { return r.expr(0).sub(x('id')); }).coerce_to("ARRAY")) ot: true - py: tbl.order_by(index=r.desc('id')).coerce_to('ARRAY') == tbl.order_by(r.desc('id')).coerce_to('ARRAY') rb: tbl.order_by(:index => r.desc(:id)).coerce_to("ARRAY").eq(tbl.order_by(r.desc(:id)).coerce_to("ARRAY")) js: tbl.order_by({index:r.desc('id')}).coerce_to("ARRAY").eq(tbl.order_by(r.desc('id')).coerce_to("ARRAY")) ot: true # test skip - cd: tbl.skip(1).count() ot: 99 - cd: tbl.skip(-1).count() ot: err('ReqlQueryLogicError', 'Cannot use a negative left index on a stream.', [0]) - cd: tbl.skip('foo').count() ot: err('ReqlQueryLogicError', 'Expected type NUMBER but found STRING.', [0]) # test limit - cd: tbl.limit(1).count() ot: 1 - cd: tbl.limit(-1).count() ot: err('ReqlQueryLogicError', 'LIMIT takes a non-negative argument (got -1)', [0]) - cd: tbl.limit('foo').count() ot: err('ReqlQueryLogicError', 'Expected type NUMBER but found STRING.', [0]) # test slice - cd: tbl.slice(1, 3).count() ot: 2 - cd: tbl.slice(5).count() ot: 95 - cd: tbl.slice(-1, -3).count() ot: err('ReqlQueryLogicError', 'Cannot use a negative left index on a stream.', [0]) - cd: tbl.slice(0, -3).count() ot: err('ReqlQueryLogicError', 'Cannot use a right index < -1 on a stream.', [0]) - cd: tbl.slice(0, -1).count() ot: err('ReqlQueryLogicError', 'Cannot slice to an open right index of -1 on a stream.', []) - cd: tbl.slice('foo', 'bar').count() ot: err('ReqlQueryLogicError', 'Expected type NUMBER but found STRING.', [0]) - cd: tbl.slice(1, null).count() ot: err('ReqlNonExistenceError', 'Expected type NUMBER but found NULL.', [0]) - cd: tbl.slice(null, 1).count() ot: err('ReqlNonExistenceError', 'Expected type NUMBER but found NULL.', [0]) - cd: tbl.slice(12, 20).count() ot: 8 - cd: tbl.slice(12, 20, :right_bound => 'closed').count() py: tbl.slice(12, 20, right_bound='closed').count() js: tbl.slice(12, 20, {right_bound:'closed'}).count() ot: 9 - cd: tbl.slice(12, 20, :left_bound => 'open').count() py: tbl.slice(12, 20, left_bound='open').count() js: tbl.slice(12, 20, {left_bound:'open'}).count() ot: 7 - cd: tbl.slice(12, 20, :left_bound => 'open', :right_bound => 'closed').count() py: tbl.slice(12, 20, left_bound='open', right_bound='closed').count() js: tbl.slice(12, 20, {left_bound:'open', right_bound:'closed'}).count() ot: 8 - cd: tbl.slice(12, -1).count() ot: err("ReqlQueryLogicError", "Cannot slice to an open right index of -1 on a stream.", []) - cd: tbl.slice(12, -1, :right_bound => 'closed').count() py: tbl.slice(12, -1, right_bound='closed').count() js: tbl.slice(12, -1, {right_bound:'closed'}).count() ot: 88 - cd: tbl.slice(12, -2).count() ot: err("ReqlQueryLogicError", "Cannot use a right index < -1 on a stream.", []) - cd: tbl.slice(12, -2, :right_bound => 'closed').count() py: tbl.slice(12, -2, right_bound='closed').count() js: tbl.slice(12, -2, {right_bound:'closed'}).count() ot: err("ReqlQueryLogicError", "Cannot use a right index < -1 on a stream.", []) - cd: tbl.slice(-12, -2).count() ot: err("ReqlQueryLogicError", "Cannot use a negative left index on a stream.", []) - cd: tbl.slice(-12, -2, :right_bound => 'closed').count() py: tbl.slice(-12, -2, right_bound='closed').count() js: tbl.slice(-12, -2, {right_bound:'closed'}).count() ot: err("ReqlQueryLogicError", "Cannot use a negative left index on a stream.", []) - cd: tbl.coerce_to('array').slice(12, 20).count() ot: 8 - cd: tbl.coerce_to('array').slice(12, 20, :right_bound => 'closed').count() py: tbl.coerce_to('array').slice(12, 20, right_bound='closed').count() js: tbl.coerce_to('array').slice(12, 20, {right_bound:'closed'}).count() ot: 9 - cd: tbl.coerce_to('array').slice(12, 20, :left_bound => 'open').count() py: tbl.coerce_to('array').slice(12, 20, left_bound='open').count() js: tbl.coerce_to('array').slice(12, 20, {left_bound:'open'}).count() ot: 7 - cd: tbl.coerce_to('array').slice(12, 20, :left_bound => 'open', :right_bound => 'closed').count() py: tbl.coerce_to('array').slice(12, 20, left_bound='open', right_bound='closed').count() js: tbl.coerce_to('array').slice(12, 20, {left_bound:'open', right_bound:'closed'}).count() ot: 8 - cd: tbl.coerce_to('array').slice(12, -1).count() ot: 87 - cd: tbl.coerce_to('array').slice(12, -1, :right_bound => 'closed').count() py: tbl.coerce_to('array').slice(12, -1, right_bound='closed').count() js: tbl.coerce_to('array').slice(12, -1, {right_bound:'closed'}).count() ot: 88 - cd: tbl.coerce_to('array').slice(12, -2).count() ot: 86 - cd: tbl.coerce_to('array').slice(12, -2, :right_bound => 'closed').count() py: tbl.coerce_to('array').slice(12, -2, right_bound='closed').count() js: tbl.coerce_to('array').slice(12, -2, {right_bound:'closed'}).count() ot: 87 - cd: tbl.coerce_to('array').slice(-12, -2).count() ot: 10 - cd: tbl.coerce_to('array').slice(-12, -2, :right_bound => 'closed').count() py: tbl.coerce_to('array').slice(-12, -2, right_bound='closed').count() js: tbl.coerce_to('array').slice(-12, -2, {right_bound:'closed'}).count() ot: 11 - def: arr = r.expr([1,2,3,4,5]) - rb: arr[1..3] ot: [2, 3, 4] - rb: arr[1...3] py: arr[1:3] ot: [2, 3] - rb: arr[1..-3] ot: [2, 3] - rb: arr[1...-3] py: arr[1:-3] ot: [2] - rb: arr[1..-1] py: arr[1:] ot: [2,3,4,5] - rb: arr[1...-1] py: arr[1:-1] ot: [2,3,4] # test nth - cd: tbl.order_by('id').nth(1) ot: {'id':1,'a':1} - cd: tbl.order_by('id').nth(-1) ot: {'id':99,'a':3} - cd: tbl.order_by('id').nth('foo').count() ot: err('ReqlQueryLogicError', 'Expected type NUMBER but found STRING.', [0]) # test is_empty - cd: tbl.is_empty() ot: false - cd: tbl.limit(0).is_empty() ot: true - cd: r.expr(1).is_empty() ot: err('ReqlQueryLogicError', 'Cannot convert NUMBER to SEQUENCE', []) - cd: r.expr("").is_empty() ot: err('ReqlQueryLogicError', 'Cannot convert STRING to SEQUENCE', []) # Pluck - cd: tbl3.pluck().nth(0) ot: {} - cd: tbl3.pluck({}).nth(0) ot: {} - cd: tbl3.pluck([]).nth(0) ot: {} - cd: tbl3.pluck('id').order_by('id').nth(0) ot: {'id':0} - cd: tbl3.pluck(['id']).order_by('id').nth(0) ot: {'id':0} - py: tbl3.pluck({'id':True}).order_by('id').nth(0) js: tbl3.pluck({'id':true}).order_by('id').nth(0) rb: tbl3.pluck({'id'=>true}).order_by('id').nth(0) ot: {'id':0} - cd: tbl3.pluck('id', 'a').order_by('id').nth(0) ot: {'id':0,'a':0} - cd: tbl3.pluck(['id', 'a']).order_by('id').nth(0) ot: {'id':0,'a':0} - py: tbl3.pluck({'id':True, 'a':True}).order_by('id').nth(0) js: tbl3.pluck({'id':true, 'a':true}).order_by('id').nth(0) rb: tbl3.pluck({'id'=>true, 'a'=>true}).order_by('id').nth(0) ot: {'id':0,'a':0} - cd: tbl3.pluck('id', 'missing').order_by('id').nth(0) ot: {'id':0} - cd: tbl3.pluck(['id', 'missing']).order_by('id').nth(0) ot: {'id':0} - py: tbl3.pluck({'id':True, 'missing':True}).order_by('id').nth(0) js: tbl3.pluck({'id':true, 'missing':true}).order_by('id').nth(0) rb: tbl3.pluck({'id'=>true, 'missing'=>true}).order_by('id').nth(0) ot: {'id':0} - cd: tbl3.pluck('id', {'b':'c'}).order_by('id').nth(0) ot: {'id':0, 'b':{'c':0}} - cd: tbl3.pluck(['id', {'b':'c'}]).order_by('id').nth(0) ot: {'id':0, 'b':{'c':0}} - cd: tbl3.pluck(1) ot: err('ReqlQueryLogicError', 'Invalid path argument `1`.', []) - py: r.expr([[{"foo":1}]]).pluck("foo") js: r.expr([[{"foo":1}]]).pluck("foo") rb: r.expr([[{"foo" => 1}]]).pluck("foo") ot: err('ReqlQueryLogicError', 'Cannot perform pluck on a sequence of sequences.', []) - py: r.expr(['a','b']).map(lambda x:r.expr({'a':1,'b':2}).pluck(x)) js: r.expr(['a','b']).map(function (x) { return r.expr({'a':1,'b':2}).pluck(x); }) rb: r.expr(['a','b']).map{|x| r.expr({'a'=>1,'b'=>2}).pluck(x)} ot: [{'a':1},{'b':2}] - py: r.expr({"foo":{"bar":1}}).pluck({"foo":{"bar":"buzz"}}) ot: {"foo":{}} # without - cd: tbl.without().order_by('id').nth(0) ot: {'id':0,'a':0} - cd: tbl.without('a').order_by('id').nth(0) ot: {'id':0} - cd: tbl.without('id', 'a').nth(0) ot: {} - cd: tbl.without('a', 'missing').order_by('id').nth(0) ot: {'id':0} - cd: tbl3.without('a', {'b':'c'}).order_by('id').nth(0) ot: {'id':0, 'b':{}} - cd: tbl3.without(['a', {'b':'c'}]).order_by('id').nth(0) ot: {'id':0, 'b':{}} - cd: tbl3.without(['a', {'b':'d'}]).order_by('id').nth(0) ot: {'id':0, 'b':{'c':0}} # Union - cd: tbl.union(tbl2).count() ot: 200 - cd: tbl.union([1,2,3]).count() ot: 103 - cd: r.expr([1,2,3]).union(tbl2).count() ot: 103 ## Offsets Of - def: ord = tbl.order_by('id') js: ord.offsetsOf(r.row('id').lt(2)) py: ord.offsets_of(r.row['id'] < 2) rb: ord.offsets_of{ |row| row['id'] < 2 } ot: [0,1] - cd: r.expr([1,2,3,4]).offsets_of(3) ot: [2] - cd: r.expr([1]).offsets_of(tbl) ot: err('ReqlQueryLogicError', 'Expected type DATUM but found TABLE:', []) - py: r.expr(1).do(lambda x: r.expr([2,1,0]).offsets_of(x)) js: r.expr(1).do(function(x){ return r.expr([2,1,0]).offsets_of(x); }) rb: r(1).do{ |x| r([2,1,0]).offsets_of x } ot: [1] # Contains - cd: tbl.contains(tbl[0]) js: tbl.contains(tbl.nth(0)) ot: true - cd: tbl.contains(tbl[0].pluck('id')) js: tbl.contains(tbl.nth(0).pluck('id')) ot: false # Difference - rb: tbl.map{|x| x['a']}.difference([0,1,2,3]).count() ot: 0 - rb: tbl.map{|x| x['a']}.difference([0,1,2]).nth(0) ot: 3 # Filter - cd: tbl3.filter({'b':{'c':0}}).pluck('id').order_by('id').nth(0) ot: {'id':0} - cd: tbl3.filter({'b':{'c':6}}) ot: [] - cd: tbl3.filter(r.literal({'id':0})) ot: [] - cd: tbl3.filter({'b':r.literal({'c':0})}).pluck('id').order_by('id').nth(0) ot: {'id':0}