Reputation: 892
I am trying to filter the array object inside a table. Here is a case where I have filtered and it works perfectly.
tags = ["school", "hollywood"]
tagsLambda = lambda post: (post["tags"].contains(tags[0])) | (post["tags"].contains(tags[1]))
d = r.db("test").table("posts").filter(
tagsLambda
).run()
But, My question is I am doing the lambda operation manually, instead I want tagsLambda
to filter all the tags
. How do I do it?
Upvotes: 2
Views: 442
Reputation: 9220
tags = ["school", "hollywood"]
tagsLambda = lambda post: (
eval('|'.join(
[r'(post["tags"].contains("' + tag + '"))' for tag in tags]
))
)
d = r.db("test").table("posts").filter(tagsLambda).run()
[ r'post["tags"].contains("' + tag + '")' for tag in tags ]
is a list comprehension. It builds a list of strings like (post["tags"].contains("school"))
for each tag in tags. The '|'.join
operation builds a string from the list of strings with '|' in between like (post["tags"].contains("school")) | (post["tags"].contains("hollywood"))
. eval evaluates the whole string.
The above code can be simplified using reduce
as
tags = ["school", "hollywood"]
tagsLambda = lambda post:
reduce(lambda x,y: x | y, [ post["tags"].contains(tag) for tag in tags])
d = r.db("test").table("posts").filter(tagsLambda).run()
For Python 3, 'functools' has to be imported to use reduce
and replace reduce
with functools.reduce
.
The second lambda can be replaced with a function.
import operator as op
reduce(op.or_, [ post["tags"].contains(tag) for tag in tags])
User generators for better result.
reduce(op.or_, ( post["tags"].contains(tag) for tag in tags))
Upvotes: 1
Reputation: 9165
I think you should be able to do something like this:
tags = ["school", "hollywood"]
r.db("test").table("posts").filter(
lambda post: post["tags"].contains(lambda tag:
r.expr(tags).contains(tag)
)
).run(conn)
See http://rethinkdb.com/api/python/contains/
Upvotes: 3