django elasticsearch dsl NestedFiled不适用于ManyToManyField



我已经能够成功地将所有模型字段声明、映射和填充到Elasticsearch Index,除了BookPrice模型上使用through属性的Price字段。如果我从文档中删除"价格"字段,则它可以正常工作。

然而,我在过去成功地构建了索引,但我认为我做了一些更改,失去了代码的完整性,现在它不起作用了。

我尝试了在帮助论坛和官方文件上找到的所有可能的组合,但没有成功。

我目前正在使用

Elasticsearch == 7.8.0
elasticsearch-dsl == 7.2.1
django-elasticsearch-dsl == 7.1.1

型号.py

class Publisher(models.Model):
publisher_name = models.CharField(max_length=50)
class BookType(models.Model):
book_type = models.CharField(max_length=20) # Hard Cover, Soft Cover, Kindle Edition, Digital PDF etc.
class Book(models.Model):
book_title = models.TextField()
book_types = models.ManyToManyField(BookType, through='BookPrice', through_fields=('book', 'book_type'))
class BookPrice(models.Model):
book_type = models.ForeignKey(Booktype, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2)

文档.py

@registry.register_document
class BookDocument(Document):
book_title = fields.TextField(
attr='book_title',
fields={
'suggest': fields.CompletionField(),
})
publisher = fields.ObjectField(properties={
'publisher_name': fields.TextField(),
})
book_types = fields.NestedField(properties={
'id': fields.IntegerField(),
'book_type': fields.TextField(),
'price': fields.FloatField()
})
class Index:
name = 'books'
settings = {'number_of_shards': 1,
'number_of_replicas': 0}
class Django:
model = Book
fields = [
'id',
'slug',
'published_date',
'pages',
]
related_models = [BookPrice, BookType]
def get_queryset(self):
return super(BookDocument, self).get_queryset().select_related('publisher', 'book_types')
def get_instances_from_related(self, related_instance):
if isinstance(related_instance, BookPrice):
return related_instance.book
return related_instance.book_set.all()

错误

Traceback (most recent call last):
File "C:UsersdevPycharmProjectsbooksvenvlibsite-packagesdjango_elasticsearch_dslfields.py", line 53, in get_value_from_instance
instance = instance[attr]
TypeError: 'BookType' object is not subscriptable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:UsersdevPycharmProjectsbooksvenvlibsite-packagesdjango_elasticsearch_dslfields.py", line 59, in get_value_from_instance
instance = getattr(instance, attr)
AttributeError: 'BookType' object has no attribute 'price'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:UsersdevPycharmProjectsbooksvenvlibsite-packagesdjango_elasticsearch_dslfields.py", line 64, in get_value_from_instance
instance = instance[int(attr)]
ValueError: invalid literal for int() with base 10: 'price'
File "C:UsersdevPycharmProjectsbooksvenvlibsite-packagesdjango_elasticsearch_dslfields.py", line 69, in get_value_from_instance
raise VariableLookupError(
django_elasticsearch_dsl.exceptions.VariableLookupError: Failed lookup for key [price] in <BookType: Hard Cover>
Exception ignored in: <generator object cursor_iter at 0x00000000052F07B0>
Traceback (most recent call last):
File "C:UsersdevPycharmProjectsbooksvenvlibsite-packagesdjangodbmodelssqlcompiler.py", line 1586, in cursor_iter
cursor.close()
sqlite3.ProgrammingError: Cannot operate on a closed database.

我解决了这个问题,并使用了prepare_foo(self, instance)方法。使用prepare_field

文档.py

def prepare_book_types(self, instance):
return instance.get_price_for_es()

型号.py

class Book(models.Model):
......
def get_price_for_es(self):
book_types= self.bookprice_set.all()
book_types_price_list = []
for x in book_types:
book_types_price_list.append({'id': x.booktype_id, 'book_type': x.booktype.book_type, 'price': x.price})
return book_types_price_list

相关内容

最新更新