Эффективный внешний ростеринг с MySQL и ejabberd
вопрос
обратите внимание,что решение этой проблемы находится непосредственно ниже, используя идею Eugen's view!
я пишу модуль чата для управляемого пользователем сайта PHP/MySQL, который позволяет двум пользователям дружить и выбрал eJabberd для системы чата.
я успешно настроил внешнюю аутентификацию с помощью демона PHP, и теперь мне удалось получить дружеские отношения в eJabberd с помощью mod_roster_odbc
и заполнения В MySQL rosterusers
таблицы вручную. После долгих раскопок мне удалось найти этот конкретный комментарий очень полезно знать, что установить для каждого столбца, чтобы представить эту дружбу в списке друзей для модуля чата.
мой текущий метод обработки дружеских отношений заключается в вставке двух строк в rosterusers
стол:
# Relationship user1 => user2
INSERT INTO rosterusers (username, jid, subscription, ask, server, type)
VALUES ('user1', 'user2@myserver.org', 'B', 'N', 'B', 'item');
# Relationship user2 => user1
INSERT INTO rosterusers (username, jid, subscription, ask, server, type)
VALUES ('user2', 'user1@myserver.org', 'B', 'N', 'B', 'item');
я не слишком доволен этим, потому что для взаимной дружбы требуется два ряда.
I поймите, что XMPP, по стандарту, позволяет одиночные и двойные связи между пользователями. Как можно было бы заключить по характеру моего вопроса, система друзей моего собственного приложения использует одну строку для представления дружбы.
мои основные вопросы:
- можно ли консолидировать эту дружбу в один ряд? Я пробовал некоторые комбинации из этого неофициальная документация, но не имел успеха. Я тестирую, подключаясь к моему серверу XMPP с помощью Клиент Pidgin.
- каков наилучший способ синхронизировать две базы данных-друзья и реестр XMPP? Я думаю, что MySQL
TRIGGER
может быть самым чистым вариантом на данный момент.
если нет, то мой вариант это изменить rosterusers
таблица и получить, что ссылаться на строку друга моего собственного приложения, так что он функционирует как внешний ключ базы данных.
Код Решения
я создал представление, как предложил Ойген. Код не самый элегантный, но я протестировал его, и он работает с eJabberd 2.1 на MySQL 5.5.
моя точная настройка использует две базы данных, поэтому я ссылаюсь на базу данных моего основного приложения явно с помощью main_database.table_name
.
код представляет собой объединение двух запросов-первый принимает пользователя, друга, а затем второй вставляет друга, пользователя. Я использую UNION ALL
для скорости и пропустить "дубликаты".
Я думаю, что это действительно отличный способ решения проблемы, поскольку никаких изменений в приложение требуется, и он обновляется мгновенно.
CREATE VIEW rosterusers AS
SELECT LCASE(ua1.Username) AS `username`, CONCAT(LCASE(ua2.Username), '@myserver.org') AS `jid`,
'B' AS `subscription`,
'N' AS `ask`,
'N' AS `server`,
'item' AS `type`,
'B' AS `subscribe`,
d1.Created AS `created_at`,
ua2.Username AS `nick`,
'' AS `askmessage`
FROM main_database.User_Friend AS `d1`
INNER JOIN main_database.User AS `ua1` ON `d1`.UserID = `ua1`.ID
INNER JOIN main_database.User AS `ua2` ON `d1`.FriendID = `ua2`.ID
WHERE d1.IsApproved = 1
UNION ALL
SELECT LCASE(ub2.Username) AS `username`, CONCAT(LCASE(ub1.Username), '@myserver.org') AS `jid`,
'B' AS `subscription`,
'N' AS `ask`,
'N' AS `server`,
'item' AS `type`,
'B' AS `subscribe`,
d2.Created AS `created_at`,
ub1.Username AS `nick`,
'' AS `askmessage`
FROM main_database.User_Friend AS `d2`
INNER JOIN main_database.User AS `ub1` ON `d2`.UserID = `ub1`.ID
INNER JOIN main_database.User AS `ub2` ON `d2`.FriendID = `ub2`.ID
WHERE d2.IsApproved = 1;
1 ответов
IIUC, стол rosterusers
только для чтения из POV вашего eJabberd
сервер приложений. Это сделало бы его простым, чтобы заменить его на view
, что создает необходимые 2 строки из 1 строки в вашей собственной таблице друзей.
не зная структуры вашей собственной таблицы дружбы, я не могу дать вам полный код, но вот что я думал о псевдо-SQL
CREATE VIEW rosterusers AS SELECT * FROM (
SELECT
selfuser.name AS username,
frienduser.jid AS jid,
-- ....,
selfuser.jid AS jid_as_id
FROM
users AS selfuser
INNER JOIN friendships ON ....
INNER JOIN users AS frienduser ON ...
UNION SELECT
frienduser.name AS username,
selfuser.jid AS jid,
-- ....,
frienduser.jid AS jid_as_id
FROM
users AS selfuser
INNER JOIN friendships ON ....
INNER JOIN users AS frienduser ON ...
);
а то
SELECT
username, jid, subscription, ask, server, type
FROM rosterusers
WHERE jid_as_id='user1@myserver.org'
должны дать вам 2 строки, по одной из каждой части UNION
в Вид