Skip to content
This repository has been archived by the owner on Jul 12, 2020. It is now read-only.

Support partial matches #36

Merged
merged 1 commit into from
Jun 21, 2018

Conversation

nusjzx
Copy link

@nusjzx nusjzx commented Jun 8, 2018

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [ ] Documentation update
• [ ] Bug fix
• [ ] New feature
• [X] Enhancement to an existing feature
• [ ] Other, please explain:

Resolves MarkBind/markbind#218

What is the rationale for this request?
Currently when searching, only entries that match all words are shown in results,
entries that match some of the words can be shown, possibly at a lower part of the results

What changes did you make? (Give an overview)
calculate the number of matches for each entries an sort the entries by the number of matches

Testing instructions:
1.run npm run docs
2.can try key in keywords from different entries. eg: "hello bugs world"

@yamgent
Copy link
Member

yamgent commented Jun 11, 2018

So now we get the OR functionality, by losing the AND functionality.

I think this feature needs further discussion, specifically whether it is useful and how we can implement it without losing what we have previously worked so hard in implementing. :P

@damithc
Copy link

damithc commented Jun 11, 2018

So now we get the OR functionality, by losing the AND functionality.

If there are three search terms, results that match all three should be on top of the results. i.e., AND is still there. In addition, we also show results that match fewer search terms. We can even show which terms are not matched. e.g.,
image

@yamgent
Copy link
Member

yamgent commented Jun 11, 2018

If there are three search terms, results that match all three should be on top of the results. i.e., AND is still there.

You are right, I forgot about that, thanks for the reminder.

That means the rank implementation is wrong then, because entries that matches multiple search terms are ranked lower:

@nusjzx
Copy link
Author

nusjzx commented Jun 11, 2018

@yamgent the new commit will solve the bug above

@@ -21,29 +21,42 @@ export default {
if (!this.data) {
return undefined;
}

function calculateMatchNum(searchTarget, regexes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this method above if (this.value.length < 2) {

title,
});
let searchTarget = [title].concat(keywords).concat(Object.values(headings)).join(' ');
let matchNum = calculateMatchNum(searchTarget, regexes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename calculateMatchNum() to getTotalMatches()

let searchTarget = [title].concat(keywords).concat(Object.values(headings)).join(' ');
let matchNum = calculateMatchNum(searchTarget, regexes);

if (matchNum) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to be a bit more explicit in the condition (i.e. if (matchNum > 0)).

Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits

@@ -15,35 +15,47 @@ export default {
},
computed: {
primitiveData() {
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((matchNum, regex) => (regex.test(searchTarget) ? matchNum + 1 : matchNum), 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matchNum -> acc

title,
});
let searchTarget = [title].concat(keywords).concat(Object.values(headings)).join(' ');
let matchNum = getTotalMatches(searchTarget, regexes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matchNum -> totalMatches

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this marked outdated?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this marked outdated?

Oops, sorry, oversight on my end.

if (this.value.length < 2) {
return [];
}
if (!this.data) {
return undefined;
}
const matches = [];
const regexes = this.value.split(' ').map(searchKeyword => new RegExp(searchKeyword, 'i'));
const regexes = this.value.split(' ').filter(searchKeyword => searchKeyword !== '')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter on next line.

title,
});
let searchTarget = [title].concat(keywords).concat(Object.values(headings)).join(' ');
let matchNum = getTotalMatches(searchTarget, regexes);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this marked outdated?

});
let searchTarget = [title].concat(keywords).concat(Object.values(headings)).join(' ');
let matchNum = getTotalMatches(searchTarget, regexes);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary empty line.

src,
title,
});
let searchTarget = [title].concat(keywords).concat(Object.values(headings)).join(' ');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the point of concatenating all headings.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not how do you wanna check isMatchingPage,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But isMatchingPage is supposed to not check for headings right? The calculation of the ranking should be independent of isMatchingPage.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const isMatchingPage = getTotalMatches(searchTarget, regexes) === matchNum;
It is comparing the totalMatches of all info(including all headings) with info (not including headings)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, how about this:

    this.data.forEach((entry) => {
        const {headings, src, title} = entry;
        const keywords = entry.keywords || '';
        let searchTarget = [title].concat(keywords).join(' ');
        const pageTotalMatches = getTotalMatches(searchTarget, regexes);
        if (pageTotalMatches > 0) {
          matches.push(Object.assign(entry, { totalMatches: pageTotalMatches }));
        }
        Object.entries(headings).forEach(([id, text]) => {
          const searchTarget = [title].concat(keywords).concat(text).join(' ');
          const totalMatches = getTotalMatches(searchTarget, regexes);
          if (totalMatches > 0) {
            matches.push({
              heading: {id, text},
              keywords,
              src,
              title,
              totalMatches,
            });
          }
        });
      });

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this will rank the page entry lower than its heading entry.

Copy link
Member

@yamgent yamgent Jun 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fine, if it matches lesser keywords it should be lower anyway.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it matches only title and keywords, it will show an entry for every heading?
That does not seem right — and makes the results unnecessarily long.

I'm not sure about ranking the page entry lower than its heading entries.
The page should be the main target; heading entries serve as quick links.
It seems pointless to show the page entry at the bottom.

@@ -15,35 +15,47 @@ export default {
},
computed: {
primitiveData() {
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((acc, regex) => (regex.test(searchTarget) ? acc + 1 : acc), 0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call it total instead of acc.

An alternative is:

regexes.filter(regex => regex.test(searchTarget)).length;

@nusjzx nusjzx force-pushed the 218-support-partial-matches branch from c7fafb5 to ef29d95 Compare June 20, 2018 03:30
Copy link
Member

@yamgent yamgent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am good with this. @acjh is this ok for you?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support partial matches
4 participants