0

I have a question, lets say I have a collection called contact :

[
    {"firstName": "Adam", "lastName":"Peter", "email":"adam@peter.com"},
    {"firstName": "Adam", "lastName":"John", "email":"adam@john.com"},
    {"firstName": "Adam", "lastName":"Petkovic", "email":"adam@petkovic.com"}
]

What I want is to search specifically, for example: I want to search "Adam peter" then I want to have a result of the first one ONLY which has Adam and peter.

I use meteor + mongo + react for my application.

Any suggestion / recommendation would be high appreciated.

Thanks for all the answers, but probably I need to ask more specific in order to get more appropriate answer.

Scenarios:

  • I only have 1 text box to search all the fields.

So:

  • when I enter "Adam", I expect to have 3 results. but when I enter "Adam Peter" I expect to have 1 result only.

  • When I enter "peter.com" it should have 1 result

  • When I enter "John", it should have 1 result

  • When I enter "Adam Pet" it should have 2 results.

Shrabanee
  • 2,706
  • 1
  • 18
  • 30
hnandarusdy
  • 412
  • 5
  • 19

3 Answers3

1

From the answer here, below query should work fine.

db.contacts.find( { firstName: /^Adam$/i, lastName: /^peter$/i });
Community
  • 1
  • 1
Sudheer Jami
  • 697
  • 6
  • 15
0

The query in MongoDB is case sensitive, if you want to query contact by ignoring case, you should use a regular expression, but it may not efficient.

db.contact.findOne({firstName: /^adam$/i, lastName: /^peter$/i})

it will much better if you always save these name value in lowercase, and query in lowercase

db.contact.findOne({firstName: 'adam', lastName: 'peter'})
ryanhex53
  • 577
  • 4
  • 15
0

Assuming that the rules that you are applying are:

  • If a single word, then that could match any field
  • two words mean "firstname surname"

In that case, you can't use text indices, but instead need to do some work before the mongo search.

First, split the words on whitespace, and then determine if there are one or two words. If there is one word, check that against all fields. If there are two, then only check the first word against the first name, and the second against the lastname.

// assuming input is in variable call 'term'
var words = term.trim().split(/\s+/) || [];

if(words.length === 0) {
    return;
}
var first = new RegExp(words[0], 'i');
if(words.length === 2) {
    var second = new RegExp(words[1], 'i');
    return Contact.find({firstName: first, lastName: second});
else if(words.length === 1) {
    return Contact.find({$or: [ {firstName: first}, {lastName: first}, {email: first}]})
}

Also, depending on how large your collection is, it might be better to wrap this up into a Meteor method, so that the search takes place on the server. Otherwise, you will have to publish the whole collection on the client to be able to do the search. That might be fine for a small collection though.

UPDATE:

Based on your examples, I think your rules are: 1. Search terms are combined with AND operator (e.g. Adam Pet returns two rows, not three). 2. Search terms use regular expression matching (Pet matches even though it's not any of the words).

Rule 2 means that text indices won't work, so you will need to build up a complex regex query document using $and and $or for each item:

// assuming input is in variable call 'term'
var words = term.trim().split(/\s+/) || [];
var query = {
    "$and": []
};
words.forEach(function(token) {
    var reg = new RegExp(token);
    var innerQ = {"$or": [ {firstName: reg}, {lastName: reg}, {email: reg}]};
    query["$and"].push(innerQ);
});
return Contact.find(query);
Nathan Webb
  • 457
  • 3
  • 10
  • Fantastic, however I actually can enter as many words as I want in order to search specifically in all my contact fields. I actually have more fields such as mobileNumber, phoneNumber... User should be able to enter whatever they think is relevant. for example: users may enter Adam 04-1234-1234. so it is not always firstname + lastName. – hnandarusdy Jun 17 '16 at 00:36
  • Can you clarify your rules in that case? It sounds like maybe you want to search on each token using AND, rather than OR? Is that right? In that case, I'll edit my answer. – Nathan Webb Jun 18 '16 at 09:47