Skip to content

Commit 4bc88e9

Browse files
committed
Auto merge of #1560 - FreeMasen:master, r=carols10cents
loosen search To address #159, It might be worth it to add a new flag for searching with the original behavior. I have played around with adding a flag to the query params, `strict` to allow the original behavior. It is very much a viable option, I didn't want to make any UI changes w/o first checking in about what it should look like.
2 parents e19275d + 346b573 commit 4bc88e9

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

src/controllers/krate/search.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ pub fn search(req: &mut dyn Request) -> CargoResult<Response> {
5858
has_filter = true;
5959
if !q_string.is_empty() {
6060
let sort = params.get("sort").map(|s| &**s).unwrap_or("relevance");
61+
6162
let q = plainto_tsquery(q_string);
6263
query = query.filter(
6364
q.matches(crates::textsearchable_index_col)
64-
.or(Crate::with_name(q_string)),
65+
.or(Crate::like_name(&q_string)),
6566
);
6667

6768
query = query.select((

src/models/krate.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ pub const MAX_NAME_LENGTH: usize = 64;
8686
type CanonCrateName<T> = self::canon_crate_name::HelperType<T>;
8787
type All = diesel::dsl::Select<crates::table, AllColumns>;
8888
type WithName<'a> = diesel::dsl::Eq<CanonCrateName<crates::name>, CanonCrateName<&'a str>>;
89+
/// The result of a loose search
90+
type LikeName = diesel::dsl::Like<CanonCrateName<crates::name>, CanonCrateName<String>>;
8991
type ByName<'a> = diesel::dsl::Filter<All, WithName<'a>>;
9092
type ByExactName<'a> = diesel::dsl::Filter<All, diesel::dsl::Eq<crates::name, &'a str>>;
9193

@@ -234,6 +236,13 @@ impl<'a> NewCrate<'a> {
234236
}
235237

236238
impl Crate {
239+
/// SQL filter with the `like` binary operator. Adds wildcards to the beginning and end to get
240+
/// substring matches.
241+
pub fn like_name(name: &str) -> LikeName {
242+
let wildcard_name = format!("%{}%", name);
243+
canon_crate_name(crates::name).like(canon_crate_name(wildcard_name))
244+
}
245+
/// SQL filter with the = binary operator
237246
pub fn with_name(name: &str) -> WithName<'_> {
238247
canon_crate_name(crates::name).eq(canon_crate_name(name))
239248
}

src/tests/krate.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,46 @@ fn exact_match_on_queries_with_sort() {
414414
assert_eq!(json.crates[3].name, "other_sort");
415415
}
416416

417+
#[test]
418+
fn loose_search_order() {
419+
let (app, anon, user) = TestApp::init().with_user();
420+
let user = user.as_model();
421+
422+
let ordered = app.db(|conn| {
423+
// exact match should be first
424+
let one = CrateBuilder::new("temp", user.id)
425+
.readme("readme")
426+
.description("description")
427+
.keyword("kw1")
428+
.expect_build(conn);
429+
// temp_udp should match second because of _
430+
let two = CrateBuilder::new("temp_utp", user.id)
431+
.readme("readme")
432+
.description("description")
433+
.keyword("kw1")
434+
.expect_build(conn);
435+
// evalrs should match 3rd because of readme
436+
let three = CrateBuilder::new("evalrs", user.id)
437+
.readme("evalrs_temp evalrs_temp evalrs_temp")
438+
.description("description")
439+
.keyword("kw1")
440+
.expect_build(conn);
441+
// tempfile should appear 4th
442+
let four = CrateBuilder::new("tempfile", user.id)
443+
.readme("readme")
444+
.description("description")
445+
.keyword("kw1")
446+
.expect_build(conn);
447+
vec![one, two, three, four]
448+
});
449+
let search_temp = anon.search("q=temp");
450+
assert_eq!(search_temp.meta.total, 4);
451+
assert_eq!(search_temp.crates.len(), 4);
452+
for (lhs, rhs) in search_temp.crates.iter().zip(ordered) {
453+
assert_eq!(lhs.name, rhs.name);
454+
}
455+
}
456+
417457
#[test]
418458
fn show() {
419459
let (app, anon, user) = TestApp::init().with_user();

0 commit comments

Comments
 (0)