8000 Edge case in combineWith:'AND' · Issue #311 · lucaong/minisearch · GitHub
[go: up one dir, main page]

Skip to content

Edge case in combineWith:'AND' #311

Open

Description

@gyzerok

Hello there! I think there is an edge case with combineWith:'AND' where search results are produced incorrectly. It's easier to explain with example then in words, so please bare with me here.

Consider the following setup:

const index = new MiniSearch({
  fields: ['text'],
  processTerm(term) {
    term = term.toLowerCase();
    switch (term) {
      case 'motorcycle':
        return [term, 'scooter']
      default:
        return term
    }
  },
  searchOptions: {
    combineWith: 'AND',
    processTerm(term) {
      term = term.toLowerCase();
      switch (term) {
        case 'motorcycle':
          return [term, 'bike']
        default:
          return term
      }
    }
  }
})

index.add({ id: 1, text: 'yamaha motorcycle' });
index.add({ id: 2, text: 'yamaha car' });

If we specify combineWith:'AND'

// returns nothing
console.log(index.search('motorcycle', { prefix: true }));
// returns id:2
console.log(index.search('yamaha car', { prefix: true }));

If we specify combineWith:'OR'

// returns id:1
console.log(index.search('motorcycle', { prefix: true }));
// returns both id:1 and id:2
console.log(index.search('yamaha car', { prefix: true }));

However what I want to achieve is

// returns id:1
console.log(index.search('motorcycle', { prefix: true }));
// returns id:2
console.log(index.search('yamaha car', { prefix: true }));

From my perspective combineWith: 'AND' should be applied such that I get the result I am looking for. So it uses AND operator between tokens, but does not use AND operator between terms for the same token. Does it make any sense?

The example here is totally made up. My actual use case is transliteration, where conversion of terms isn't lossless (some letters could disappear) which results in the problem I've described here.

Activity

  1. lucaong commented on Sep 14, 2026

    @lucaong
    Owner

    Hi @gyzerok , sorry for the late reply. The issue here is that motorcycle is expanded by the custom processTerm to ['motorcycle', 'bike'], and only one of those matches the indexed document.

    I understand you want to support "synonyms", so one can search for "bike" and still find a document containing "motorcycle". One way you can do this is by performing the expansion of synonyms only upon indexing, and not upon search. Something like:

    const index = new MiniSearch({
      fields: ['text'],
      processTerm(term) {
        term = term.toLowerCase();
        switch (term) {
          case 'motorcycle':
            return [term, 'bike']
          default:
            return term
        }
      },
      searchOptions: {
        combineWith: 'AND',
        processTerm: (term) => term.toLowerCase()
      }
    })

    Now, documents including the term "motorcycle" will be indexed as if they also include the term "bike", but search is unaffected, so the issue with AND does not arise. Would this solve your problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0