Ответ 1
"Фильтровать как ресурс" - идеальный такт для этого.
Вы можете выполнить фильтрацию фильтра в ресурсе фильтра и вернуть идентификатор фильтра.
PUT является idempotent, поэтому, даже если фильтр уже существует, вам просто нужно обнаружить, что вы видели фильтр раньше, чтобы вы могли вернуть правильный идентификатор для фильтра.
Затем вы можете добавить параметр фильтра к вашим другим запросам, и они могут захватить фильтр для использования для запросов.
GET/лекарства? filter = 1234 & page = 4 & pagesize = 20
Я бы запускал необработанные фильтры через какой-то процесс канонизации, просто чтобы иметь нормализованный набор, так что, например, filter "firstname = Bob lastname = Eubanks" идентичен "lastname = Eubanks firstname = Bob". Это только я, хотя.
Единственная реальная проблема заключается в том, что со временем вам может потребоваться устаревать некоторые фильтры. Вы можете просто обнулить запрос, если кто-то сделает запрос с отсутствующим или устаревшим фильтром.
Изменить ответный вопрос...
Давайте начнем с основ.
Просто вы хотите указать фильтр для использования в запросах, но эти фильтры (потенциально) задействованы и сложны. Если это было просто/лекарства/1234, это не было бы проблемой.
Эффективно, вам всегда нужно отправить фильтр в запрос. Вопрос заключается в том, как представить этот фильтр.
Основная проблема с такими вещами, как сеансы в системах REST, заключается в том, что они обычно управляются "вне диапазона". Когда вы, скажем, идете и создаете лекарство, вы PUT или POST на ресурс медикаментов, и вы получите ссылку на этот препарат.
С сеансом вы, как правило, возвращаете cookie или, возможно, другой токен, чтобы представить этот сеанс. Если ваш PUT к ресурсу медикаментов также создал сеанс, тогда, по правде говоря, ваш запрос создал два ресурса: лекарство и сеанс.
К сожалению, когда вы используете что-то вроде файла cookie, и вам нужен этот файл cookie для вашего запроса, имя ресурса больше не является истинным представлением ресурса. Теперь это имя ресурса (URL) и файл cookie.
Итак, если я делаю GET на ресурсе с именем /medications/search, а cookie представляет сеанс, и на этом сеансе есть фильтр, вы можете увидеть, как это происходит, это имя ресурса/медикаменты/search, на самом деле не очень полезно. У меня нет всей информации, необходимой мне для эффективного использования, из-за побочного эффекта cookie и сеанса и фильтра в нем.
Теперь вы могли бы переписать имя:/medicications/search? session = ABC123, эффективно внедряя файл cookie в имя ресурса.
Но теперь вы столкнулись с типичным контрактом сессий, особенно в том, что они недолговечны. Итак, этот ресурс назван менее полезным, долгосрочным, а не бесполезным, менее полезным. Прямо сейчас этот запрос дает мне интересные данные. Завтра? Возможно нет. Я получу какую-то неприятную ошибку в связи с отсутствием сеанса.
Другая проблема заключается в том, что сеансы обычно не управляются как ресурс. Например, они обычно являются побочным эффектом, vs явно управляется с помощью GET/PUT/DELETE. Сессии также являются "мусорной кучей" состояния веб-приложения. В этом случае мы просто надеемся, что сессия правильно заполнена тем, что необходимо для этого запроса. На самом деле мы этого не знаем. Опять же, это побочный эффект.
Теперь, пусть немного повернуть его на голову. Пусть использование/лекарства/поиск? Filter = ABC123.
Очевидно, что случайно это выглядит одинаково. Мы просто изменили имя с 'session' на 'filter'. Но, как обсуждалось, фильтры в этом случае являются "ресурсом первого класса". Они должны быть созданы, управляться и т.д. Так же, как лекарство, JPEG или любой другой ресурс в вашей системе. Это ключевое различие.
Конечно, вы можете рассматривать "сеансы" как ресурс первого класса, создавать их, напрямую вставлять материал в них и т.д. Но вы можете видеть, как, по крайней мере, с ясности, сеанс "первого класса" не является Действительно хорошая абстракция для этого случая. Используя сеанс, он, похоже, идет к уборщикам и передает весь ваш кошелек или портфель. "Да, билет где-то там, выкапывайте то, что вы хотите, дайте мне мою одежду", особенно по сравнению с чем-то явно подобным фильтру.
Итак, вы можете видеть, как на расстоянии 30 000 футов между фильтром и сеансом нет большой разницы. Но когда вы приближаетесь, они совсем разные.
С ресурсом фильтра вы можете сделать их постоянными навсегда и всегда. Вы можете их закончить, вы можете делать все, что хотите. Сессии, как правило, имеют заранее продуманную семантику: короткие живые, длительность соединения и т.д. Фильтры могут иметь любую семантику, которую вы хотите. Они полностью отделены от того, что приходит с сеансом.
Если бы я это делал, как бы я работал с фильтрами?
Я бы предположил, что я действительно не забочусь о содержимом фильтра. В частности, я сомневаюсь, что я когда-нибудь запрошу "все фильтры, которые ищут по имени". На этом этапе это кажется неинтересной информацией, поэтому я не буду ее создавать.
Далее, я бы нормализовал фильтры, как я уже упоминал выше. Убедитесь, что эквивалентные фильтры действительно эквивалентны. Вы можете сделать это, сортируя выражения, обеспечивая, чтобы имена полей были прописными буквами или что-то еще.
Затем я бы сохранил фильтр как документ XML или JSON, в зависимости от того, что более удобно или подходит для приложения. Я бы дал каждому фильтру уникальный ключ (естественно), но я бы также сохранил хэш для фактического документа с фильтром.
Я бы сделал это, чтобы быстро найти, если фильтр уже сохранен. Поскольку я нормализую это, я "знаю", что XML (скажем) для логически эквивалентных фильтров будет идентичным. Поэтому, когда кто-то переходит к PUT или добавляет новый фильтр, я бы сделал чек на хеш, чтобы узнать, сохранилось ли оно ранее. Я, возможно, вернусь более чем к одному (хеши могут столкнуться, конечно), поэтому мне нужно проверить фактические данные XML, чтобы увидеть, соответствуют ли они.
Если фильтры совпадают, я возвращаю ссылку на существующий фильтр. Если нет, я бы создал новый и вернул это.
Я также не разрешаю фильтр UPDATE/POST. Поскольку я передаю ссылки на эти фильтры, я бы сделал их неизменными, поэтому ссылки могут оставаться в силе. Если бы я хотел получить фильтр "роль", скажем, "получить весь фильтр истечения срока действия лекарств", тогда я бы создал ресурс "named filter", который связывает имя с экземпляром фильтра, так что фактические данные фильтра могут изменяться, но имя остается неизменным.
Разумеется, также, что во время создания вы находитесь в состоянии гонки (два запроса пытаются сделать тот же фильтр), поэтому вам придется учитывать это. Если ваша система имеет высокий объем фильтра, это может стать потенциальным узким местом.
Надеюсь, это прояснит проблему для вас.