Javascript 使用查询字符串的最终搜索

Javascript 使用查询字符串的最终搜索,javascript,node.js,reactjs,express,query-string,Javascript,Node.js,Reactjs,Express,Query String,这是一个很长的问题,请耐心听我说 我们有一个运行在Express、Mongo、React和Redux上的应用程序。我已经编写了中间件和路由处理程序,它们通过获取查询字符串来处理传入的请求 以下是后端的代码: 后端:节点,Express Peopleservices.js const people = require("../models/Person"); // creating the filter function const findBy = filter => { // lo

这是一个很长的问题,请耐心听我说

我们有一个运行在ExpressMongoReactRedux上的应用程序。我已经编写了中间件和路由处理程序,它们通过获取查询字符串来处理传入的请求

以下是后端的代码:

  • 后端:节点,Express
  • 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
    };
    
    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);
        }
      });
    };
    
    这就是我们获取查询字符串并转换为mongo可理解查询的地方

    PeopleRouters.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
    };
    
    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。前端:反应,重复

    我们将通过用户交互生成查询字符串,有三个输入字段,即姓名性别,和年龄。根据给定的组合,我们创建要发送到服务器的最终查询字符串。这是这样做的:

    从用户捕获数据的表单:

    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>
        );
      }
    
    一旦我们将所有用户数据存储在状态中,我们将其传递给我们的动作创建者:

    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 });
      }
    };
    
    Action creator使用Axios发出请求,并显示结果。但是正如你所看到的,我只能做一点点的if和else,以得到一些组合。因此,我正在寻找一种更好的方法

    我试过什么?

    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>
        );
      }
    
    • 我尝试过重构过滤器,并在服务器端使用query.params
    • 我已强制用户输入所有字段(简单案例)
    • 我制作了一个向导表单,收集了所有数据并发送了结果
    • 我已经编写了一段代码,用于解析接收到的状态,并根据长度创建了查询字符串
    尽管如此,代码目前还可以,许多应用程序(如Jira)也面临同样的问题,并通过首先强制分类简化了过程!我坚持要想出一个很酷的算法来实现这个神奇的效果


    我亲爱的工程师朋友,聪明的人,在这件事上给我启发吧!我真的不喜欢那些if和else!这些都是罪

    您可以这样简化它:-

    //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)从参数生成查询字符串,这将提供更多方法:-

    这里有很多。我认为如果你能把注意力集中在这个问题上,删除一些没有增加问题的代码,这会有所帮助。如果我理解正确:您正在询问如何处理传递给
    fetchPeople
    的任意数量的位置参数。理论上,它可以得到
    ['name','','gender']
    ['','age','gender']
    或这三个值的任意组合。您需要将它映射到用于HTTP请求的命名键/值对?没错,有很多!我只是想让它尽可能全面。。你说得很对。这里的问题是尝试根据用户输入生成查询字符串,例如,如果用户将“name”留空,并填写“age”和“gender”,我们的查询字符串如下->所有人?name=&age\u gt=20&gender=male!其他情况也是如此!你看,使用这个查询字符串,我们无法从服务器获得任何合理的结果,这就是这里的问题…伙计!我不想降低答案的等级,但如果将对象连接到字符串,则会发出如下请求->“您尝试过解决方案吗?它不会像你说的那样。您需要接收fetch people中的第一个参数,它将是一个对象。不要在fetch people中传播参数。是的,我们得到typeError,因为我们无法将未定义或null转换为objectObject.keys(args).forEach(key=>{您是否像上面提到的那样使用对象调用fetch people?似乎您没有传递对象。