Окончательный поиск со строками запроса - PullRequest
2 голосов
/ 05 мая 2019

Это довольно длинный вопрос, поэтому, пожалуйста, потерпите меня

У нас есть приложение, которое работает на Express , Mongo , React и Redux .Я написал промежуточное оборудование и обработчики маршрутов, которые обрабатывают входящий запрос, получая строку запроса.

Вот код для бэкэнда:

  1. Бэкэнд: Узел, Экспресс

Peopleservices.js

const people = require("../models/Person");

// creating the filter function
const findBy = filter => {
  // loop on filter props
  const query = {};

  for (prop in filter) {
    // if the prop contains gt or lt we should change it to mongo style query
    if (prop.includes("_")) {
      let finalQuery = {};
      let parts = prop.split("_");
      query[parts[0]] = parts[1];
      finalQuery[`$${parts[1]}`] = filter[prop];
      query[parts[0]] = finalQuery;
    } else {
      // if the prop does not containg gt or lt, just return the same query
      query[prop] = filter[prop];
    }
  }
  // finally, return the query
  return people.find(query);
};

module.exports = {
  findBy
};

Здесь мы получаем строку запроса и конвертируем в понятный монго запрос.

PeopleRouters.js

module.exports = app => {
  // calling services
  const service = require("../services/peopleService");

  // Route to handle everyone
  app.get(["/everyone"], async (req, res) => {
    try {
      const filter = req.query || {};
      const all = await service.findBy(filter);
      res.status(200).send(all);
    } catch (ex) {
      next(ex);
    }
  });
};

Затем мы вызываем маршрутизатор с правильным запросом

2.Внешний интерфейс: React, Redux

Мы создадим строку запроса при взаимодействии с пользователем, есть три поля ввода, а именно: Имя , Пол и Возраст .На основе заданной комбинации мы создаем конечную строку запроса для отправки на сервер.Это делается следующим образом:

Форма для сбора данных от пользователя:

App.js

render() {
    // the form, ideally could have it's own component
    return (
      <div className="ui container">
        <div className="row" />
        <div className="row">
          <div className="ui two column centered grid">
            <div className="column">
              <div className="ui form">
                <form className="ui form" onSubmit={this.handleSubmit}>
                  <div className="field">
                    <label>Name:</label>
                    <input
                      type="text"
                      name="name"
                      value={this.state.name}
                      onChange={this.handleChange}
                    />
                  </div>
                  <div className="field">
                    <select
                      name="age"
                      value={this.state.age}
                      onChange={this.handleChange}
                    >
                      <option value="">Select Age Range</option>
                      <option value="_gte=20">Above 20</option>
                      <option value="_lt=20">Below 20</option>
                    </select>
                  </div>
                  <div className="field">
                    <select
                      className="ui fluid dropdown"
                      name="gender"
                      value={this.state.gender}
                      onChange={this.handleChange}
                    >
                      <option value="">Select Gender</option>
                      <option value="female">Female</option>
                      <option value="male">Male</option>
                    </select>
                  </div>
                  <div className="ui buttons">
                    <button type="submit" className="ui positive button active">
                      Search
                    </button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
        <div className="ui link cards">{this.renderContent()}</div>
      </div>
    );
  }

После этого получите элементы и обработайте запрос, который будет отправлен нашему создателю действия на стороне приложения Redux :

  handleChange = event => {
    this.setState({
      [event.target.name]: event.target.value
    });
  };

  // submitting the form
  handleSubmit = event => {
    event.preventDefault();
    this.props.fetchPeople(this.state.name, this.state.age, this.state.gender);
  };

Как только мы сохраним все пользовательские данныев состоянии мы передаем его нашему создателю действия:

import axios from "axios";
import { FETCH_PEOPLE } from "./types";

export const fetchPeople = (...args) => async dispatch => {
  // launching the default state
  if (!args[0] && !args[1] && !args[2]) {
    const response = await axios.get(`/everyone`);
    dispatch({ type: FETCH_PEOPLE, payload: response });
  }
  // if the name is empty, we will run the query for the gender and age
  else if (!args[0] && args[1] && args[2]) {
    console.log("we here?");
    const response = await axios.get(
      `/everyone?age${args[1]}&gender=${args[2]}`
    );
    dispatch({ type: FETCH_PEOPLE, payload: response });
  } else {
    // populating with user's input
    const response = await axios.get(
      `/everyone?name=${args[0]}&age${args[1]}&gender=${args[2]}`
    );
    dispatch({ type: FETCH_PEOPLE, payload: response });
  }
};

Создатель действия делает запрос, используя Axios , и результаты появляются.Но, как вы можете видеть, я мог бы сделать немного , если и еще , чтобы охватить только несколько комбинаций.Таким образом, я ищу лучший способ сделать это.

Что я пробовал?

  • Я пробовал рефакторинг фильтра и идущий запрос.params путь на стороне сервера
  • Я заставил пользователя ввести все поля (простой случай)
  • Я создал форму мастера, собрал все данные и отправилрезультаты
  • Я написал код для анализа полученного состояния и создал строку запроса, основанную на длине

Несмотря на то, что код в настоящее время в порядке, и многие приложения, такие как Jiraстолкнулись с той же проблемой и упростили процесс, сначала создав категорию!Я настаиваю на том, чтобы придумать крутой алгоритм, который делает волшебство!

Мой дорогой друг, инженеры, мудрые люди, просветите меня в этом вопросе!Мне действительно не нравятся эти if и elses !это грехи!

1 Ответ

2 голосов
/ 05 мая 2019

Вы можете упростить это следующим образом: -

//Pass object with keys and values from form values as arguments

this.props.fetchPeople({
  name: this.state.name,
  age: this.state.age,
  gender: this.state.gender
});



 // or more flexible approach will be to spread user input values

this.props.fetchPeople({...this.state});



// Make a genQueryString function
 const genQueryString = (args={}) => {
    let queryString = "";
    Object.keys(args).forEach((key) => {
      if(args[key]) {
        if(key === "age") {
          queryString+= `${key}${args[key]}&`;
        } else {
          queryString+= `${key}=${args[key]}&`
        }
      }
    });
    return queryString;
}

export const fetchPeople = (args) => async dispatch => {


  const response = await axios.get(
    `/everyone?${genQueryString(args)}`
  );

  dispatch({ type: FETCH_PEOPLE, payload: response });
  }
};

Или вы также можете использовать библиотеку npm, такую ​​как qs, для генерации строки запроса из аргументов, которая предоставит больше методов: - https://www.npmjs.com/package/qs

...