Elixir PostgreSQL - выберите запрос, возвращающий результаты, которые не соответствуют предложению WHERE - PullRequest
0 голосов
/ 02 октября 2019

У меня есть эта функция, которая выбирает магазины и их товары из моей базы данных:

def create_unique_shop_query_no_keyword(categories, shop_ids) do
    products_shops_categories = from p in Product,
    join: ps in ProductShop, on: p.id == ps.p_id,
    join: s in Shop, on: s.id == ps.s_id,
    join: pc in ProductCategory, on: p.id == pc.p_id,
    join: c in Subcategory, on: c.id == pc.c_id,
    distinct: s.id,
    where: c.id in ^categories,
    where: s.id in ^shop_ids,
    group_by: [s.id, s.name],
    select: %{products: fragment(
      "json_agg( DISTINCT (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)) AS products",
      p.id,
      p.name,
      p.brand,
      p.description,
      p.image,
      p.rating,
      p.number_of_votes,
      ps.not_in_shop_count,
      ps.is_in_shop_count,
      ps.price,
      p.not_vegan_count,
      p.vegan_count),
      shop: fragment(
        "json_agg( DISTINCT (?, ?, ST_X(?), ST_Y(?), ?, ?, ?, ?, ?)) AS shop",
        s.id,
        s.name,
        s.point,
        s.point,
        s.place_id,
        s.street,
        s.suburb,
        s.city,
        s.street_number
        )
      }
  end

У меня есть другая функция, которая делает то же самое, но с ключевым словом, добавленным в набор, который проверяет ключевое слово(не обязательно полное слово) в названии продукта или марке продукта:

def create_unique_shop_query(keyword, categories, shop_ids) do
    products_shops_categories = from p in Product,
    join: ps in ProductShop, on: p.id == ps.p_id,
    join: s in Shop, on: s.id == ps.s_id,
    join: pc in ProductCategory, on: p.id == pc.p_id,
    join: c in Subcategory, on: c.id == pc.c_id,
    distinct: s.id,
    where: c.id in ^categories,
    where: s.id in ^shop_ids,
    where: like(p.name, ^("%#{keyword}%")),
    or_where: like(p.brand, ^("%#{keyword}%")),
    group_by: [s.id, s.name],
    select: %{products: fragment(
      "json_agg( DISTINCT (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)) AS products",
      p.id,
      p.name,
      p.brand,
      p.description,
      p.image,
      p.rating,
      p.number_of_votes,
      ps.not_in_shop_count,
      ps.is_in_shop_count,
      ps.price,
      p.not_vegan_count,
      p.vegan_count),
      shop: fragment(
        "json_agg( DISTINCT (?, ?, ST_X(?), ST_Y(?), ?, ?, ?, ?, ?)) AS shop",
        s.id,
        s.name,
        s.point,
        s.point,
        s.place_id,
        s.street,
        s.suburb,
        s.city,
        s.street_number
        )
      }
  end

Функция top без ключевого слова работает как задумано. Но в функции, которая имеет ключевое слово, результаты содержат магазины, где идентификатор магазина (s.id) не находится в shop_ids. Почему это?

1 Ответ

2 голосов
/ 02 октября 2019

У вас есть or_where, поэтому ваше условие запроса по существу ....

(c.id in categories) and (s.id in shop_ids) and (p.name like keyword) or (p.brand like keyword)

Пока p.brand похож на ключевое слово, оно будет совпадать.

Это, вероятно, то, что вы ищете, группируя условие ИЛИ в пределах И, где для соответствия ключевого слова.

...
where: c.id in ^categories,
    where: s.id in ^shop_ids,
    where: like(p.name, ^("%#{keyword}%")) or like(p.brand, ^("%#{keyword}%")),
...

Это переводит его в

(c.id in categories) and (s.id in shop_ids) and (p.name like keyword or p.brand like keyword)

...