wade icon indicating copy to clipboard operation
wade copied to clipboard

Search object properties?

Open bajalovic opened this issue 8 years ago • 10 comments

Is it possible to index objects by some properties, and then search by those fields?

For example

const search = Wade([{id: 1, name: "John Doe", email: "[email protected]"}, {id: 2, name: "Another User", email: "[email protected]"}])

and then to search by query and property (that may be optional)

search("John", "name")
// or
search("com") // search all fields?

Or should I create different search instances for each property I want to search for?

bajalovic avatar Jul 24 '17 08:07 bajalovic

It's not possible to do right now, but I could try adding it. It would increase the size to over 1kb though. I suppose I can accomplish this by holding an index and a property name in the trie, so I can increment the score for a property.

I would also have to add a new option to Wade, stating which properties should be searched over in case of properties not being strings (such as id in this case).

For now, I'd suggest making a new Wade instance for each property, maybe I can add some sort of plugin for this.

kbrsh avatar Jul 24 '17 16:07 kbrsh

Why not to just add to_str?

ghost avatar Aug 09 '17 19:08 ghost

It's harder because Wade generates and updates scores based on the array index, not object property names. @ctl

kbrsh avatar Aug 09 '17 19:08 kbrsh

@kbrsh hi Kabir, good job on building a tiny search engine Curious if you're planning to add that object reference so we could include ids.

Perhaps your lib was truly meant for minimalistic structure.

thanks

jeveloper avatar Nov 12 '17 16:11 jeveloper

@jeveloper Thanks! I might, but not right now. Currently, I'm working on making the search index more memory efficient.

For now, you can try something like:

const documents = [
  {
    id: "foo",
    text: "bar"
  },
  {
    id: "bar",
    text: "baz"
  }
];

// Process into array of strings
let processed = [];
for(let i = 0; i < documents.length; i++) {
  const doc = documents[i];
  let str = "";

  for(let key in doc) {
    str += " " + doc[key];
  }

  processed.push(str);
}

const search = Wade(processed);

kbrsh avatar Nov 12 '17 17:11 kbrsh

Thank you , that would be problematic , appreciate the tip

jeveloper avatar Nov 12 '17 21:11 jeveloper

@kbrsh would it work to do something like this? I mean it looks like it should work, but will the results still be good?

const objects = [
  {x: '1', y: '2', z: '3'},
  {x: '4', y: '5', z: '6'},
  ...etc...
];

const search = Wade(objects.map(obj => `${obj.x} ${obj.y} ${obj.z}` ));

search('2 3'); // Will it return the expected results?

samuelgozi avatar Aug 07 '19 12:08 samuelgozi

@samuelgozi It depends on what you want. For example, with your search query 2 3, if you want the 2 to specifically search in the property x and the 3 to search in the property y, then it won't work. However, they will work if you want to search for text that can be in any object field. In your example above, Wade returns:

[
	{
		"index": 0,
		"score": 1.3333333333333333
	}
]

kbrsh avatar Aug 07 '19 17:08 kbrsh

I want full text search for all of the fields combined, so it should work. Thanks for the clarification.

Edit: the question is, will it still be effective when the text gets very long? In other words, does the algorithm just look for the occurrence of words, or does it take into account the distance between them?

samuelgozi avatar Aug 07 '19 20:08 samuelgozi

It doesn't have anything special for the distance between words. Do you have an example of your use case for this? I think I can answer better if I have more information about your use case.

kbrsh avatar Aug 07 '19 21:08 kbrsh