使用查询字符串的终极搜索
The ultimate search with query strings
这个问题比较长,请多多包涵
我们在 Express、Mongo、 上有一个 运行 的应用程序]React 和 Redux。我已经编写了通过获取查询字符串来处理传入请求的中间件和路由处理程序。
这是后端代码:
- 后端:节点、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
};
这是我们获取查询字符串并转换为 mongo 可理解查询的地方。
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
我们将通过用户交互生成查询字符串,输入字段有姓名、性别、[=49]三个字段=]年龄。基于给定的组合,我们创建要发送到服务器的最终查询字符串。这是这样做的:
从用户获取数据的表单:
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 });
}
};
Action creator 使用 Axios 发出请求并显示结果。但如您所见,我只能做一点点 if 和 else 来覆盖几个组合。因此,我正在寻找一种更好的方法。
我尝试了什么?
- 我已经尝试重构过滤器并在服务器端query.params方式
- 我强制用户输入所有字段(最简单的情况)
- 我制作了一个向导表格,收集了所有数据并发送了结果
- 我编写了一段代码来剖析接收到的状态,并根据长度创建了查询字符串
虽然目前代码没问题,Jira等很多应用都遇到过同样的问题,先通过强制分类来简化流程!我坚持想出一个很酷的算法,它可以发挥魔力!
亲爱的工程师朋友,各位智者,请赐教!我真的不喜欢那些 if 和 elses!这些都是罪过!
你可以这样简化它:-
//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 });
}
};
或者您也可以使用像 qs 这样的 npm 库从参数生成查询字符串,这将提供更多方法:-
https://www.npmjs.com/package/qs
这个问题比较长,请多多包涵
我们在 Express、Mongo、 上有一个 运行 的应用程序]React 和 Redux。我已经编写了通过获取查询字符串来处理传入请求的中间件和路由处理程序。
这是后端代码:
- 后端:节点、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
};
这是我们获取查询字符串并转换为 mongo 可理解查询的地方。
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
我们将通过用户交互生成查询字符串,输入字段有姓名、性别、[=49]三个字段=]年龄。基于给定的组合,我们创建要发送到服务器的最终查询字符串。这是这样做的:
从用户获取数据的表单:
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 });
}
};
Action creator 使用 Axios 发出请求并显示结果。但如您所见,我只能做一点点 if 和 else 来覆盖几个组合。因此,我正在寻找一种更好的方法。
我尝试了什么?
- 我已经尝试重构过滤器并在服务器端query.params方式
- 我强制用户输入所有字段(最简单的情况)
- 我制作了一个向导表格,收集了所有数据并发送了结果
- 我编写了一段代码来剖析接收到的状态,并根据长度创建了查询字符串
虽然目前代码没问题,Jira等很多应用都遇到过同样的问题,先通过强制分类来简化流程!我坚持想出一个很酷的算法,它可以发挥魔力!
亲爱的工程师朋友,各位智者,请赐教!我真的不喜欢那些 if 和 elses!这些都是罪过!
你可以这样简化它:-
//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 });
}
};
或者您也可以使用像 qs 这样的 npm 库从参数生成查询字符串,这将提供更多方法:- https://www.npmjs.com/package/qs