graphile-contrib/postgraphile-plugin-connection-filter

Faceted Search: 'Refine your Search'

joshheyse opened this issue · 3 comments

Full Disclosure: This is my first PostGraphile (and graphql) app. I am definitely still learning.

I am trying to implement a search page with similar features to CDWs "Refine your Search" where the user can select 0 or more values from an attribute type, if no values are selected the attribute type filter is ignored.

Some SQL sudo code would be:

SELECT title, brand, processor, price FROM computers WHERE (
  (isNil($selectedBrands) OR brand IN $selectedBrands) AND
  (isNil($selectedProcessors) OR processor IN $selectedProcessors)
) 

I tried to use query variables as the LHS for a condition, but couldn't seem to get that to work.

Is this possible to do with the plugin connection filter? Do you have any recommendations on this type of query?

@joshheyse you should have no problem handling this, just use the and field in the filter expression and add as many conditions as you want

If you set connectionFilterAllowNullInput: true via graphileBuildOptions, it will ignore any null properties in the filter input object. Here's a full example:

drop schema if exists app_public cascade;
create schema app_public;

create table app_public.computer (
  id integer primary key,
  title text,
  brand text,
  processor text,
  price numeric
);

insert into app_public.computer (id, title, brand, processor, price) values
  (1, 'Acer Chromebase', 'Acer', 'Core i3',  799.00),
  (2, 'Apple iMac', 'Apple', 'Core i5', 1499.00),
  (3, 'ASUS Vivo', 'ASUS', 'Core i5', 999.00);
const express = require("express");
const { postgraphile } = require("postgraphile");
const ConnectionFilterPlugin = require("postgraphile-plugin-connection-filter");

const app = express();

app.use(
  postgraphile("postgres://localhost:5432/issue_122", "app_public", {
    appendPlugins: [ConnectionFilterPlugin],
    graphiql: true,
    graphileBuildOptions: {
      connectionFilterAllowNullInput: true, // default: false
    },
  })
);

app.listen(5000);
query Computers($brands: [String!], $processors: [String!]) {
  allComputers(filter: {
    brand: { in: $brands }
    processor: { in: $processors }
  }) {
    nodes {
      id
      title
      brand
      processor
      price
    }
  }
}
// variables
{
  "brands": ["Apple", "Acer"],
  "processors": null
}
{
  "data": {
    "allComputers": {
      "nodes": [
        {
          "id": 1,
          "title": "Acer Chromebase",
          "brand": "Acer",
          "processor": "Core i3",
          "price": "799.00"
        },
        {
          "id": 2,
          "title": "Apple iMac",
          "brand": "Apple",
          "processor": "Core i5",
          "price": "1499.00"
        }
      ]
    }
  }
}

There are some caveats with this approach; see https://github.com/graphile-contrib/postgraphile-plugin-connection-filter#handling-null-and-empty-objects for more information.

[semi-automated message] I'm going to close this issue due to lack of activity, but please feel free to continue the conversation below. 🙂