weixsong / elasticlunr.js

Based on lunr.js, but more flexible and customized.
http://elasticlunr.com
MIT License
2.03k stars 148 forks source link

Searching fields using boolean AND doesn't yield any results #8

Closed hydrajump closed 8 years ago

hydrajump commented 8 years ago

Hi,

I'm coming from lunrjs because I'm interested in your field searching feature.

My index json looks similar to this:

{
  "index": [{
    "name": "my name is A",
    "array1": [
      "array1 value1",
      "array1 value2"
    ],
    "array2": [
      "array2 value1",
      "array2 value2"
    ],
    "id": "nameA"
  }, {
    "name": "my name is B",
    "array1": [
      "array1 value4",
      "array1 value10"
    ],
    "array2": [
      "array2 value1",
      "array2 value5"
    ],
    "id": "nameB"
  }]
}

What I need to be able to do is search this index using queries such as this (I know the syntax is not correct):

1.

q = idx.search(+name:"my name is B")
q.length == 1
q.results == ["nameB"]

2.

q = idx.search(+array1:"array1 value1")
q.length == 1
q.results == ["nameA"]

3.

q = idx.search(+array1:"array1 value1" +array2:"array2 value1")
q.length == 2
q.results == ["nameA", "nameB"]

The problem is that when I use my real json file and run the searches above I don't get the expected results.

  1. I've tried the approach below, but it doesn't work and returns zero results. It's as if there is a problem matching the exact string "my name is B".
q = idx.search("my name is B", {
    fields: {
        name: {}
    },
    bool: "AND"
});
q.length
  1. Similar problem to (1). I want to find the exact string "array1 value1" in the field "array1", but here too the results are zero when I used AND.
q = idx.search("array1 value1", {
    fields: {
        array1: {}
    }
});
q.length == 1
  1. Here I want to find the exact string "array1 value1" in the field "array1" AND "array2 value1" in the field "array2".
q = idx.search("array1 value1 array2 value1", {
    fields: {
        array1: {},
        array2: {}
    }
});
q.length == 2

I hope you understand what I mean and can help me find a solution to these issues. Thanks.

weixsong commented 8 years ago

Hi, @hydrajump , thanks for this feedback.

Firstly, before indexing documents, you need to tell elasticlunr which field that you want to index by:

var index = elasticlunr(function () {
    this.addField('name');
    this.addField('array1');
    this.addField('array2')
    this.setRef('id');
});

then, index your json data, to make it clear, I defined two json data by your data:

var doc1 = {
    "name": "my name is A",
    "array1": [
      "array1 value1",
      "array1 value2"
    ],
    "array2": [
      "array2 value1",
      "array2 value2"
    ],
    "id": "nameA"
  }

var doc2 = {
    "name": "my name is B",
    "array1": [
      "array1 value4",
      "array1 value10"
    ],
    "array2": [
      "array2 value1",
      "array2 value5"
    ],
    "id": "nameB"
  }

and then, index these two documents:

index.addDoc(doc1);
index.addDoc(doc2);

then search,

index.search("my name is B", {
    fields: {
        name: {}
    },
    bool: "AND"
});

and the results is:

[Objectref: "nameA" score: 0.5945348918918356__proto__: Object]

And, you are right, currently elasticlunr has some issue about find the documents from field that consist of array.

Thanks very much for reporting this issue. I will fix this issue as soon as possible.

hydrajump commented 8 years ago

@weixsong thanks for your quick reply!

Yeah, I've done all the things that you said, but as you confirmed the issue with array fields is unfortunately the reason that the results are not what they should be.

weixsong commented 8 years ago

Hi, @hydrajump , finally fixed this issue. Follow the following codes:

var index = elasticlunr(function () {
    this.addField('name');
    this.addField('array1');
    this.addField('array2')
    this.setRef('id');
});

var doc1 = {
    "name": "my name is A",
    "array1": [
      "array1 value1",
      "array1 value2"
    ],
    "array2": [
      "array2 value1",
      "array2 value2"
    ],
    "id": "nameA"
  }

var doc2 = {
    "name": "my name is B",
    "array1": [
      "array1 value4",
      "array1 value10"
    ],
    "array2": [
      "array2 value1",
      "array2 value5"
    ],
    "id": "nameB"
  }

index.addDoc(doc1);
index.addDoc(doc2);

index.search("my name is B", {
    fields: {
        name: {}
    },
    bool: "AND"
});

Query results:

index.search("my name is B", {
    fields: {
        name: {}
    },
    bool: "AND"
});

And another query:

index.search("array1 value1", {
    fields: {
        array1: {}
    },
    bool: "AND"
});

Query results:

index.search("array1 value1", {
    fields: {
        array1: {}
    }, bool: "AND"
});

Thanks very much for reporting this issue.

hydrajump commented 8 years ago

Hey @weixsong, thank you for fixing this issue so fast :smile: