У меня в последнем стабильном релизе Kate Mobile (Lite), скачанном три дня назад через Гугл Плей, ту же ошибку выбивало при переходе в раздел аудио, и ничего не загружалось. Так что однозначно или лыжи не едут, или что-то не так с этим методом... или с вк. Или с Kate :(
Официальное приложение, кстати, нормально работает. Даже без установки сервисов от гугл.
Даниил Лепке, попробовал послать запрос, сделал всё по инструкции, токен получил. Так эти собаки заморозили страницу, на которой тестил. Написали, что "обнаружена подозрительная активность". Как быть? Может, проблема в том, что у меня на смартфоне уже стояло официальное приложение с этим client_id и секретом, и там уже был получен токен?
Как думаете, что надёжнее: воспользоваться мобильной версией, если там так всё ещё можно, или попытаться сделать через браузер и расширение к нему? То есть расширение может общаться с веб-сервером, периодически проверяя очередь задач, и складывать туда ответы. Ответы двух типов: результаты поиска по аудио в виде списка треков (исполнитель, название, длительность, айди) и ссылка собственно на сам трек. Правда тут ещё может возникнуть проблема, что ссылка скорее всего будет привязана к IP сервера, поэтому придётся и файлы проксировать.
Мне просто хочется вернуть возможность прикреплять аудио к сообщениям в своём мессенджере, а доступ к закрытому API мне, думается, никто не даст с моей мизерной аудиторией.
LB777: разве на ретине всё должно было выглядеть не в два раза меньше? Или так браузеры на маке работают, что там увеличение по дефолту идёт, а в Вашем случае оно как раз всё портит?
Проблема не в том, что неоткуда сграбить музыку. Проблема в другом. Вот есть у меня, допустим, мессенджер. И там была функция - прикрепить аудио. Пользователю удобно получить сразу список своих аудиозаписей из вк через API (поиск я и так не использовал, много хлама в выдаче бывает), а теперь эту функцию пришлось выпилить, т.к. она больше не работает...
S0ulReaver: а есть какие-то исследования о том, как технически реализована защита? Наверняка ведь можно её обойти. Браузер-то как-то данные забирает с сервера.
Rsa97: я знаю про EXPLAIN, но как-то не умею читать его выдачу. Он пишет про использование каких-то индексов, а я даже не всегда в курсе, откуда они берутся. Например, написано using index, а какой - не сказано. А их иногда несколько у таблицы. И вообще форма вывода там специфичная.
Кстати, и это тоже логично. В вашем варианте сначала скорее всего просматривается таблица тегов благодаря оптимизатору, а она очень мала (сейчас там меньше 10 строк). Дальше выбираются из первой таблицы уже нужные строки (для этого можно использовать частичный индекс в случае people и первичный ключ id в случае names). Отбирается их ровно столько, сколько строк в user_tags (если у нас нет дублирований во второй таблице). И выборка идёт по индексу. Дальше группировка и оценка числа элементов в группе идёт уже в маленькой временной таблице.
А то, что сотворил я, хоть и смотрится неплохо - это похоже fullscan по таблице people, в которой несколько тысяч строк как минимум, и для каждой итерации ещё не самый лёгкий подзапрос делается.
Я тут вспомнил, что такая таблица есть, и хранит она пары (id, имя) в единственном экземпляре (там нет записей с двумя одинаковыми id). Стоит наверное использовать её. Оказывается, JOIN работает быстрее чем вложенный запрос, во всяком случае в логе меньше операций при этом. Там весь JOIN занимал 0.0009 секунды, а тут только удаление временной таблицы занимает 0.006 мс.
А самое изящное на ваш взгляд решение было бы какое? Создать дублирующую таблицу, где будут только id людей из вк в качестве единственной колонки (с требованием уникальности)? Или просто оставить мой текущий вариант
SELECT DISTINCT `user_id` FROM `people` WHERE (SELECT COUNT(*) FROM `user_tags` WHERE `people`.`user_id`=`user_tags`.`user_id` AND `tag_id` IN (1,2))=2
Rsa97: да, прошу прощения, я уже понял) Там потому что нет как таковой таблицы пользователей. А таблица people хранит пары (user_id, event_id) - вроде информации о посещении разных событий. Вот что значит неудачное название для таблицы выбрано...
Тогда да, DISTINCT только в помощь :)
Но это не объясняет, почему INNER JOIN выдавал пустой результат.
Rsa97: спасибо, не заметил. Теперь работает. Не очень правда понял, почему в случае с LEFT JOIN всё "сыпится". Кроме заполнения нулевыми значениями в документации особых оговорок нет про специфику LEFT/RIGHT JOIN вроде.
Такой ещё вопрос немного не по теме: почему при выполнении данного запроса я получаю три одинаковых строки, ведь по идее должна проходиться вся таблица `people`, и для каждой её строки должен вычисляться подзапрос (и в зависимости от его значения строка берётся в выдачу или не берётся). Откуда дублирование строк?
SELECT `user_id` FROM `people` WHERE (SELECT COUNT(*) FROM `user_tags` WHERE `people`.`user_id`=`user_tags`.`user_id` AND `tag_id` IN (1,2))=2
А, чёрт, ну логично. Соотнесённый запрос выполняется для каждой найденной строки. На этапе анализа внешнего WHERE никакой `count` ещё не существует :)
Тогда логичнее оставить последний вариант. Хотя механизм работы третьего варианта я так и не до конца понял. Видимо, для HAVING всё равно с чем работать, и тут он просто создаёт одну большую группу и фильтрует её. Оставляя, конечно же, дубли строк.
Rsa97: смотрите, я немного поменял запрос, добавив вложенный запрос для наглядности происходящего, сути он вроде не меняет
SELECT `people`.`user_id`, (SELECT COUNT(*) FROM `user_tags` WHERE `tag_id` IN (1,2) AND `user_id`=`people`.`user_id`) AS `count` FROM `people` LEFT JOIN `user_tags` ON `people`.`user_id`=`user_tags`.`user_id` AND `tag_id` IN (1,2) WHERE `tag_id` IS NOT NULL GROUP BY `user_tags`.`user_id` HAVING `count`=2 - не работает, пустой результат
SELECT `people`.`user_id`, (SELECT COUNT(*) FROM `user_tags` WHERE `tag_id` IN (1,2) AND `user_id`=`people`.`user_id`) AS `count` FROM `people` LEFT JOIN `user_tags` ON `people`.`user_id`=`user_tags`.`user_id` AND `tag_id` IN (1,2) WHERE `tag_id` IS NOT NULL AND `count`=2 - не работает, пишет, что `count` является неизвестной колонкой
SELECT DISTINCT `people`.`user_id`, (SELECT COUNT(*) FROM `user_tags` WHERE `tag_id` IN (1,2) AND `user_id`=`people`.`user_id`) AS `count` FROM `people` LEFT JOIN `user_tags` ON `people`.`user_id`=`user_tags`.`user_id` AND `tag_id` IN (1,2) WHERE `tag_id` IS NOT NULL HAVING `count`=2 - работает, хотя HAVING без GROUP BY - это что-то странное конечно
SELECT `people`.`user_id`, (SELECT COUNT(*) FROM `user_tags` WHERE `tag_id` IN (1,2) AND `user_id`=`people`.`user_id`) AS `count` FROM `people` LEFT JOIN `user_tags` ON `people`.`user_id`=`user_tags`.`user_id` AND `tag_id` IN (1,2) WHERE `tag_id` IS NOT NULL GROUP BY `user_id` HAVING `count`=2 - тоже работает
Как вы это объясните? По логике то, что вы написали, должно было работать, но оно не хочет :)
Rsa97: хм, почему-то ваше решение работает только для одного тега. Я что-то делаю не так, или что-то мы не учли? К слову, даже для того чтобы работало с одним пришлось модифицировать запрос, добавив "WHERE `tag_id` IS NOT NULL", потому что при JOIN там где не находит - MySQL комбинирует строки со строками с нулевыми значениями в колонках, где условие не может быть выполнено.
Официальное приложение, кстати, нормально работает. Даже без установки сервисов от гугл.