Как интегрировать пользовательский входной аргумент в набор запросов Graphene DjangoFilterConnectionField?

Мне интересно, какой самый чистый способ интегрировать пользовательский входной аргумент Graphene DjangoFilterConnectionField в набор запросов по умолчанию?

Я повторяю следующий класс Graphene Query, пользовательский входной атрибут которого пытается интегрировать функцию PgVector CosineDistance :

      class Query(graphene.ObjectType):

    all_the_small_things = DjangoFilterConnectionField(
        VectorNode,
        embedding=graphene.List(graphene.Float),
    )

    def resolve_all_the_small_things(
        root,
        info,
        **kwargs,
    ):
        from pgvector.django import CosineDistance

        annotations = {}

        if kwargs.get("embedding"):
            annotations["embedding"] = CosineDistance(
                "embedding", kwargs.pop("embedding")
            )

        if annotations:
            # How best to integrate this into the existing behavior?
            # VectorNode.objects.annotate(**annotations)
            # now use filter functionality provided by
            # the default resolver.
  

Я хотел бы расширить поведение запроса по умолчанию (т. е. фильтрацию), если предоставлен пользовательский ввод, и использовать поведение по умолчанию как есть, если это не так. Нужно ли мне реализовать свой собственный набор запросов и/или набор фильтров? Есть ли способ отразить/изменить поведение по умолчанию, используя аргументы функции?

Примечание. Я думаю, что долгосрочным ответом на этот вопрос будет добавление поддержки столбцов PG Vector в Graphene и/или создание подкласса фильтров django-filters, но мне действительно нужно понять, как все это сочетается, прежде чем серьезно думать о том, как подойти к любому из что вверх по течению.

1 ответ

Чтобы интегрировать пользовательский входной аргумент в набор запросов по умолчанию Graphene DjangoFilterConnectionField:

  1. Создайте собственный набор фильтров

  2. Переопределитьget_querysetметод:

            from django_filters import FilterSet, filters
    from graphene_django.filter import DjangoFilterConnectionField
    
    class VectorFilterSet(FilterSet):
        cosine_distance = filters.Float()  # Define your custom input argument here
    
        class Meta:
            model = VectorNode
            fields = []  # Specify other fields for filtering if needed
    
         class Query(graphene.ObjectType):
    
        all_the_small_things = DjangoFilterConnectionField(
            VectorNode,
            filterset_class=VectorFilterSet,  # Use your custom FilterSet
            cosine_distance=graphene.Float(),  # Add the custom input argument to the Query field
        )
    
        def resolve_all_the_small_things(
            root,
            info,
            **kwargs,
        ):
            from pgvector.django import CosineDistance
    
            queryset = VectorNode.objects.all()
    
            cosine_distance = kwargs.pop("cosine_distance", None)
            if cosine_distance is not None:
                queryset = queryset.annotate(
                    cosine_distance=CosineDistance("embedding", cosine_distance)
                )
    
            return queryset
    

Если ваши требования становятся более сложными или вам нужен более детальный контроль над поведением фильтрации, вы можете рассмотреть возможность реализации собственного преобразователя или создания собственного поля подключения, которое расширяет DjangoFilterConnectionField.

Другие вопросы по тегам