фильтровать результаты запроса, используя хранимую процедуру базы данных в Акведуке - PullRequest
0 голосов
/ 18 апреля 2020

Я создал Aqueduct API с базой данных PostgresSql, и я пытаюсь запрашивать пользователей поблизости от местоположения (ограничено радиусом). Моя проблема состоит в том, что функция, которая вычисляет расстояние, является хранимой процедурой (для оптимизации этой операции), но у меня есть проблемы с использованием этой хранимой процедуры базы данных. Я нашел решение с помощью предиката запроса (см. Код ниже), но теперь моя проблема: как сослаться на столбец таблицы и передать его в процедуру? (в моем случае r.lat и r.long должны ссылаться на столбцы lat и long в текущей проверенной записи таблицы)

Код контроллера: Примечание (в моем случае r.lat и r.long должны ссылаться на lat и длинные столбцы в текущей проверенной записи таблицы)

@Operation.get()
  Future<Response> getRequests({
    @Bind.query("nearby_location") Map<String, double> location,
    @Bind.query("parent_id") int parentID,
    @Bind.query("status_id") int statusID,
    @Bind.query("active") bool active,
    @Bind.query("radius") double radius = 1,
  }) async {
    final query = Query<HelpRequest>(context);

    if (statusID != null) {
      query.where((n) => n.status).identifiedBy(statusID);
    }

    if (active != null) {
      query.where((n) => n.active).equalTo(active);
    }

    if (location != null && statusID != null) {
      query.predicate = QueryPredicate(
          "parent_id IS NULL "
          "AND status_id = @status_id "
          "AND active = @active "
          "AND CalculateDistance(r.lat, r.long, @lat, @long) < @radius",
          {
            'radius': radius,
            'lat': location['lat'],
            'long': location['long'],
            'status_id': statusID,
            'active': active
          });
    }

    query..join(object: (r) => r.helpTopic)..join(object: (r) => r.status);

    return Response.ok(await query.fetch());
  }

Код модели My User: (я использую самоссылку)

class User extends ManagedObject<_User>
    implements _User, ManagedAuthResourceOwner<_User> {
  @Serialize(input: true, output: false)
  String password;

  @override
  void willUpdate() {
    updatedAt = DateTime.now().toUtc();
  }

  @override
  void willInsert() {
    updatedAt = DateTime.now().toUtc();
    createdAt = DateTime.now().toUtc();
  }
}

class _User extends ResourceOwnerTableDefinition {
  @Column(unique: true, nullable: true)
  String nickName;

  String firstName;
  String lastName;

  /// this field defines the user type (active=helper, !active=help getter)
  @Column(defaultValue: "'true'")
  bool active;

  DateTime birthday;

  String street;
  String houseNumber;
  String zipCode;
  String country;
  String city;

  double long;
  double lat;
  String placeId;

  @Column(nullable: true)
  String telephone;

  @Column(nullable: true)
  String mobile;

  @Relate(#users)
  SecurityRole securityRole;

  EmailConfirmation emailConfirmation;

  IdConfirmation idConfirmation;

  ForgetPassword forgetPassword;

  ManagedSet<HelpRequest> requests;

  DateTime createdAt;
  DateTime updatedAt;
}

Обратите внимание, что мой оператор SQL будет выглядеть следующим образом это если я не использую предикат:

final map = await query.context.persistentStore.execute(
    "SELECT id, parent_id, user_id, helpTopic_id, description, street, "
    "houseNumber, zipCode, country, city, long, lat, placeId, "
    "contactName, contactPhone, active, rating, notes, status_id, "
    "updatedAt, createdAt FROM request AS r"
    "WHERE parent_id IS NULL "
    "AND status_id = @status_id "
    "AND CalculateDistance(r.lat, r.long, @lat, @long) < @radius",
    substitutionValues: {
      'radius': radius,
      'lat': location['lat'],
      'long': location['long'],
      'status_id': statusID
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...