My model definition is as follows (a simplified model of the one being used in actual product. There are a coupe of other fields:
from django.db import models
from taggit.managers import TaggableManager
from django.contrib.postgres.search import SearchVectorField
from django.contrib.postgres.indexes import GinIndex
class Product(models.Model):
tags = TaggableManager()
search_vector = SearchVectorField(null=True)
class Meta:
indexes = [
GinIndex(fields=['search_vector'])
]
I run make migrations and migrate commands. These work correctly.
I then run the following set of commands to build the index:
search_vector = SearchVector('tags__name')
Product.objects.all().update(search_vector=search_vector)
I end up getting the following error:
django.core.exceptions.FieldError: Joined field references are not permitted in this query
This is clearly caused by the tags__name
field, but I am not sure how to solve it.
Can someone please explain what I would need to do in order to run the above commands correctly?
Thanks!
I think I’ve run across this before. I believe I’ve solved it using an annotate
before. Try creating an annotated field, then using that in the update
.
Product.objects.annotate(
inline_search_vector=SearchVector('tags__name')
).update(search_vector=F('inline_search_vector'))
Thanks @CodenameTim ,
I still seem to be hitting upon the error when using that technique:
django.core.exceptions.FieldError: Joined field references are not permitted in this query
Hmm, maybe it was using a Subquery
.
@zigzagdoom I was able to confirm the way I handled it was with a Subquery
instance.
Thanks a lot @CodenameTim , I will take a look
@zigzagdoom were you able to solve this issue? I couldn’t make it work with a “Subquery” instance
@CodenameTim can you help with subquery for the above example.
From the docs example we have:
from django.db.models import OuterRef, Subquery
newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
We’re not going to use it exactly, but it’ll be something close.
Let’s say Post.latest_activity
is a new datetime field we’ve added and we want to update all Post
instances to reflect the latest created_at from their comments.
newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
Post.objects.annotate(
latest_comment_datetime=Subquery(newest.values('created_at')[:1])
).update(
latest_activity=F('latest_comment_datetime')
)
thanks for the quick response. tried to apply the subquery to the above post from @zigzagdoom brings out another error
since the tags is m2m, and a post can have multiple tags, restristicitng to one (using slice [:1]) doesn’t help.
If you would like help with your problem please include more information about your situation. A good question will include what you’re trying to do, what you’re expecting to see and what you’re actually encountering. If it’s code related, please share the code as well. If there’s an error, include the error message and stacktrace.
@CodenameTim thanks, I solved the problem with subquery and StringAgg.
For others who are directed here from google for postgres full text search adding an m2m field or django-taggit package for tags, here is how i solved the error join not permitted error (similar to what @zigzagdoom got)
django.core.exceptions.FieldError: Joined field references are not permitted in this query
when trying this code
search_vector = SearchVector('tags__name')
Product.objects.all().update(search_vector=search_vector)
I used a StringAgg and used value expresions to add to the SearchVector, something like below pseudocode
Product.objects.all().annotate(tagnames=StringAgg("tags__name", delimiter=", ")).update(search_vector=SearchVector("title", "description") + SearchVector(Value("tagnames")))
1 Like