Как мне сделать этот поиск и order_by на DBIx :: Class :: ResultSet - PullRequest
2 голосов
/ 07 августа 2010

Определение проблемы.

У меня есть несколько клиентов с несколькими пользователями. Каждый клиент должен иметь возможность связывать пользовательские данные с пользователем, выполнять поиск и заказ по.


Решение для базы данных:

Таблица пользовательских полей, которая определяет таблицу пользовательских полей. У него есть идентификатор и имя. Он имеет отношение has_many с таблицей Userfields (она же «атрибуты»).

Таблица Userfields имеет идентификатор пользователя, идентификатор пользовательского поля, содержимое и идентификатор. Он принадлежит к таблице Useraccounts (также называемой "useraccount") и пользовательским полям (также называемой "customfield")


Предлагаемый выбор оператора, который я хочу:

Это отборное утверждение, которое достигает и производит то, что мне нужно.

SELECT ua.*, (
    SELECT content FROM Userfields uf
    INNER JOIN Customfields cf
        ON cf.id = uf.customfieldid
    WHERE cf.name = 'Mothers birthdate'
    AND uf.uid=ua.uid
) AS 'Mothers birthdate',
    (
    SELECT content FROM Userfields uf
    INNER JOIN Customfields cf
        ON cf.id = uf.customfieldid
    WHERE cf.name = 'Join Date' AND
    uf.uid=ua.uid
) AS 'Join Date'
FROM UserAccounts ua
ORDER BY 'Mothers birthdate';

В этом случае они могут быть любыми из 0 ... x операторов sub select в операторе select, и любой из них или ни один из них может не захотеть быть упорядоченным.


Вопрос

Как мне добиться этого с помощью -> поиска в моем наборе результатов класса dbix или как добиться того же результата при поиске в моем наборе результатов класса dbix?

Вот как я обычно выбираю из своей таблицы Useraccounts, хотя я не уверен, как сделать сложное утверждение, которое я хочу отсюда.

my @users = $db->resultset('Useraccounts')->search(
    undef,
    {
        page        => $page,
        join        => 'attributes',
        ...
    });

Спасибо за ваше время.

-pdh

1 Ответ

2 голосов
/ 07 августа 2010

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

Во-первых, (при условии, что вашТаблица userfields имеет отношение own_to с таблицей customfields, которая называется customfield)

my $mbd = $userfields_rs->search(
    {
      'customfield.name' => 'Mothers birthdate',
      'uf.uid' => \'me.uid' # reference to outer query
    },
    {
      join => 'customfield',
      alias => 'uf', # don't shadow the 'me' alias here.
    }
)->get_column('content')->as_query;

# Subqueries and -as don't currently mix, so hack the SQL ourselves
$mbd->[0] .= q{ AS 'Mothers Birthdate'};

Литерал me.uid, с которым сопоставляется uf.uid, является несвязанной переменной - это поле uidиз запроса, в который мы в конечном итоге собираемся поместить этот запрос в качестве подвыбора.По умолчанию DBIC создает псевдоним таблицы, к которой обращается запрос me;если бы вы дали ему другой псевдоним, вы бы использовали здесь что-то другое.В любом случае, вы можете повторить этот as_query бизнес с любым количеством различных полей, просто изменив имя поля (если вы умны, вы напишите метод для их генерации) и поместите их в массив,так что теперь давайте предположим, что @field_queries - это массив, содержащий $mbd выше, а также еще один, основанный на дате присоединения, и все, что вам нравится.

Как только вы это сделаете, это так же просто, как и...

my $users = $useraccounts_rs->search(
    { }, # any search criteria can go in here,
    {
      '+select' => [ @field_queries ],
      '+as' => [qw/mothers_birthdate join_date/], # this is not SQL AS
      order_by => {-asc => 'Mothers birthdate'},
    }
);

, которая будет включать каждый из подзапросов в выборку.

Теперь о грустной части: на данный момент все это на самом деле не будет работать, потому что подзапросы с заполнителями не работают должным образом.Так что сейчас вам нужен дополнительный обходной путь: вместо 'customfield.name' => 'Mothers birthdate' в поиске подвыбора сделайте 'customfield.name' => \q{'Mothers birthdate'} - это использует литеральный SQL для имени поля ( BE ОСТОРОЖНО внедрения SQL здесь!),что позволит избежать ошибки заполнителя.Но в недалеком будущем эта ошибка будет устранена, и приведенный выше код будет работать нормально, и мы обновим ответ, чтобы вы знали, что это так.

См. DBIx :: Class:: ResultSource order_by документация

...