Design of advanced search function for form data

background

"Search" is a very high utilization function in our daily Internet access. The purpose of search is to quickly retrieve the target data. Users enter certain characteristics of the target data as search conditions, and after searching, they can get data that meets the corresponding characteristics. The more detailed the input features, the more accurate the results will be.

However, for the convenience of use, the general default search will not allow users to configure too many conditions, so the search we contact daily is a simplified version of the search. However, when the amount of data increases, in order to accurately obtain the target data, we often need to configure more conditions and adjust the relationship between various conditions. In this case, we will find that the simple search of fixed conditions and relationships can no longer meet the demand. At this time, we need a more complete search function, namely "advanced search".

Design ideas

First, let's talk about the design idea. As shown in the figure above, we can find that the search statement is composed of multiple conditions, and each condition is composed of fields, comparators and values. Then users only need to configure each condition according to their needs. There are several details to consider:

  1. In fact, the types of search condition values are not uniform: for example, the comparators of numbers and strings should be different;
  2. Whether the relationship between various conditions needs to be met completely or any one;

The functional interface realized according to this idea is shown in the figure below:

Detailed explanation of implementation technology

Next, let's talk about how to implement it. Let's take a look at the type definition of the generated filter criteria:

type Condition = {
key: string; // key of qualified field
op: string; // Operator
value: FormValue; // The type of value is the type of value output by the form component
}

type FilterTag = 'should' | 'must';

type FilterConfig = {
  condition: Condition[];
  tag: FilterTag;
}

The meaning here is:

  1. Each Condition corresponds to a Condition;
  2. FilterTag represents the relationship between each condition, should represents passing the filter when any condition is met, and must represents passing the filter when all conditions are met;
  3. The final output is FilterConfig;

Implementation of conditional configuration

To get this FilterConfig, we need to do five steps:

1. Create a blank condition:

\7.png)

2. Select the form fields to use as search criteria

The first drop-down selection box is to select the form fields you want to use as search criteria. Open the drop-down box as shown in the figure;

  • Options selected from the drop-down box = form own field + system field:

\3.png)

  • Form fields:

\4.png)

3. Select the operator

Since the value types of different form fields are not necessarily the same, all operators should display the corresponding operator set according to the type of the selected form field.

At present, the form value types of low code platforms are: String, Boolean, Number, LabelValue, Datetime, array < String|boolean|Number|LabelValue >. According to these types, you need to define the corresponding operator set in advance.

const OPERATORS_STRING = [
  {
    label: 'be equal to',
    value: 'eq',
  },
  {
    label: 'vague',
    value: 'like',
  },
];

const OPERATORS_NUMBER = [
  {
    label: 'be equal to',
    value: 'eq',
  },
  {
    label: 'greater than',
    value: 'gt',
  },
  {
    label: 'less than',
    value: 'lt',
  },
  {
    label: 'Greater than or equal to',
    value: 'gte',
  },
  {
    label: 'Less than or equal to',
    value: 'lte',
  },
  {
    label: 'Not equal to',
    value: 'ne',
  },
];

const OPERATORS_DATE = [
  {
    label: 'Range',
    value: 'range',
  },
];

const OPERATORS_BOOL = [
  {
    label: 'be equal to',
    value: 'eq',
  },
  {
    label: 'Not equal to',
    value: 'ne',
  },
];

const OPERATORS_ARRAY_MULTIPLE = [
  {
    label: 'Also include',
    value: 'fullSubset',
  },
  {
    label: 'Include any one',
    value: 'intersection',
  },
];

const OPERATORS_LABEL_VALUE = [
  {
    label: 'be equal to',
    value: 'eq',
  },
  {
    label: 'Not equal to',
    value: 'ne',
  },
];

When render ing, use this tool function to get the required collection:

function getOperators(type: string) {
  switch (type) {
  case 'array':
    return OPERATORS_ARRAY_MULTIPLE;
  case 'number':
    return OPERATORS_NUMBER;
  case 'datetime':
    return OPERATORS_DATE;
  case 'boolean':
    return OPERATORS_BOOL;
  case 'label-value':
    return OPERATORS_LABEL_VALUE;
  default:
    return OPERATORS_STRING;
  }
}

4. Fill in the value of the search criteria field

The value of the search criteria field needs to meet the type requirements and condition restrictions of the field. For example, if the component type of the selected field is NumberPicker and the field limits the number range to 0-100, a number input box should be displayed and only numbers in the range of 0-100 can be entered.

\8.png)

The implementation code of the condition value input box is as follows:

function FieldSwitch(type) {
  switch (type) {
  case 'CheckboxGroup':
  case 'Select':
  case 'RadioGroup':
  case 'MultipleSelect':
    return (
      <SelectField />
    );
  case 'NumberPicker':
    return (
      <InputNumber />
    );
  case 'DatePicker':
    return (
      <DatePicker.RangePicker />
    );
  case 'CascadeSelector':
    return (
      <CascadeSelector />
    );
  case 'OrganizationPicker':
    return (
      <OrganizationPicker />
    );
  case 'UserPicker':
    return (
      <UserPicker />
    );
  default:
    return <Input />;
  }
}

5. Select the relationship between the conditions

The last step is to select the relationship between the conditions.

\9.png)

  • All: the relationship between each condition is and (&), which will be searched only when it is met at the same time;
  • Any: the relationship between conditions is or (|), which will be searched as long as one of the conditions is met;

In this way, when we click search, we can get a FilterConfig, then convert this structure to some extent, and pass it to the interface to realize data search.

PS: the search of form data is implemented by [Elasticsearch], so there will be a mutual conversion from FilterConfig to the AST of Elasticsearch. The specific implementation steps here will be broken down in the next chapter.

\5.png)

summary

Ordinary search cannot configure the relationship between conditions and the comparison symbols of conditions, but the advanced search we introduced solves this problem. Through the combination of various search conditions, we can get the target data more quickly. It has greatly improved the efficiency of our work.

\6.png)

quote

Elasticsearch: https://www.elastic.co/cn/

This article is composed of blog one article multi posting platform OpenWrite release!

Keywords: JSON

Added by kaushikgotecha on Mon, 17 Jan 2022 18:12:49 +0200