11

i have parse.com database. i have column in a table named "text". i have to find text with multiple keys matching with AND condition. i tried it all ways. i tried to use:

    PFQuery *query=[PFQuery queryWithClassName:@"post"];
    [query whereKey:@"text" containedIn:Array];

or

    PFQuery *query=[PFQuery queryWithClassName:@"post"];
    [query whereKey:@"text" containsAllObjectsInArray:Array];        

or

PFQuery *query=[PFQuery queryWithClassName:@"post"];
for (NSString *str in filtersArray) {

    [query whereKey:@"text" containsString:str];

}

but no one works. please guide me if parse sdks supports this or not totally? if yes how can i achieve the results. many thanks in advance :)

EIDT:

for example i have three entries in database as text:

  1. "i have a data entry"

  2. "i can not find something in data"

  3. "how can i do this"

if pass "i" and "this" it should return entry (3)

if pass "i" and "data" it should return entry (1,2)

if pass "i" and "else" it should return nothing

Imran Ahmed
  • 1,023
  • 1
  • 11
  • 23
  • 1
    Is the column `text` of type string? And you'd like to determine if that string contains one or more words? The only way to do this with a query is via `whereKey:matchesRegex:`, which is very expensive. Another idea is limit the result with some other criterion, then enumerate the result testing for substring containment in app logic. Limit network cost of this idea by doing it in cloud code. – danh Jul 12 '15 at 22:43
  • i need to determine if a text contains both keywords ?if yes text will be returned if any of them is missing in the text, that text will be rejected by query. – Imran Ahmed Jul 13 '15 at 21:22

4 Answers4

2

The reason your query doesn't work is because Parse does not support having the same constraint (in this case 'containsString:') more than once on the same key.

So, what I would suggest is to query for a regular expression which will match all of your filter strings using - (instancetype)whereKey:(NSString *)key matchesRegex:(NSString *)regex.

NSArray *qryStrings = @[str1, str2, str3, ....]; //strings you are trying to match

//string which will hold our regular expression
NSString *regexString = @"^"; //start off the regex

for (NSString *str in qryStrings) { //build the regex one filter at a time
    regexString = [NSString stringWithFormat:@"%@(?=.*%@)", regexString, str];
}

regexString = [NSString stringWithFormat:@"%@.*$", regexString]; //finish off the regex

PFQuery *query = [PFQuery queryWithClassName:@"post"];
[query whereKey:@"text" matchesRegex:regexString];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (!error) {
        //objects array contains matching rows with matching strings
    }
    else {
        NSLog(@"%@ %@", error, [error userInfo]);
    }
}];
keither04
  • 321
  • 2
  • 6
0

Depending on the speed requirements of your query and the number of objects being queried, I would try separating the results using componentsSeparatedByString: after enumerating through the results array using something like: for(NSString *string in results). After separating each string into an individual array, use an if(...) statement that determines if that collection of words contains each word searched.

Code example:

NSMutableArray *searchResults = [[NSMutableArray alloc] init];
PFQuery *query=[PFQuery queryWithClassName:@"post"];

// consider setting a limit, depending on the number of posts
// consider sorting the query as needed

NSArray *posts = [query findObjects];
for(NSString *text in posts)           
{
  NSArray *words = [text componentsSeparatedByString:@" "];   // use SeperatedByCharactersInSet: for . , or anything else you'd need
  switch ([filterArray count])
  {
    case 1:
      if([words containsObject:filterArray[0]])
      {
         [searchResults addObject:text];
      } 

      break;

    case 2:
      if([words containsObject:filterArray[0]] && 
         [words containsObject:filterArray[1]])
      {
         [searchResults addObject:text];
      } 

      break;

    // case n:
    //   if([words containsObject:filterArray[0]] && 
    //      [words containsObject:filterArray[1]] &&
    //      [words containsObject:filterArray[n]])
    //   {
    //      [searchResults addObject:text];
    //   } 
    //
    //   break;

    default:
      break;
  }

 _filteredResults = [NSArray arrayWithArray:searchResults]; // local global instance of results - use for maintaining order (be sure to clear it between searches)

The _filteredResults array should be what you're wanting. Be sure to consider speed and the character separators used in the search though.

ChrisHaze
  • 2,800
  • 16
  • 20
  • @imran because we've attempted to solve a problem you're dealing with, and you don't like our particular approach, you downvote everyone who has attempted to help you? – ChrisHaze Jul 22 '15 at 20:26
-1

You simply just need to use whereKey:containsString:

And if you want to use additional parameters, you just simply add a subQuery

soulshined
  • 9,612
  • 5
  • 44
  • 79
  • it will take all the posts matching any keywords of both. it will not work – Imran Ahmed Jul 13 '15 at 21:20
  • @ImranAhmed when I said subQuery I meant inner query. Either way you do it, it's going to be a high API request so it's personal preference how you go about this. – soulshined Jul 14 '15 at 13:38
  • subQuery is exactly "orQueryWithSubQueries" in parse sdk. but i need actually "andWithSubQuries" which is not there in parse. – Imran Ahmed Jul 14 '15 at 16:05
  • Right. I meant sub as in 'another layer'. I chose the wrong wording though. I meant sub as in 'inner query'. So you do your first query for the first search term, then inside the findObjects callback do another query for those found objects that include the second search term. Inner query – soulshined Jul 14 '15 at 16:08
  • if i go this way i will have to implement it locally. PFQuery will not support local fetched object filtration. – Imran Ahmed Jul 14 '15 at 16:42
  • what part about that means you have to implement it locally? – soulshined Jul 14 '15 at 17:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83243/discussion-between-imran-ahmed-and-soulshined). – Imran Ahmed Jul 14 '15 at 17:21
  • i haven't find any way to perform sub queries as your described in your answer. – Imran Ahmed Jul 22 '15 at 06:26
-2

Your solution need to modify a bit.

Like this.

PFQuery *query=[PFQuery queryWithClassName:@"post"];
[query whereKey:@"text" containedIn:Array];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
//what your logic you want to write there might comes some records that are counts two times so you can remove those using NSSet
 }];
Danial Hussain
  • 2,488
  • 18
  • 38