Start a new topic

NSRegularExpression and mutiQueries

Hello all,



So I currently have a app that queries the database by both geocoding and then matching a string in an array of strings. So I have an array of strings on a object in the database and for this object to be displayed I currently geocode it and then also match a string to that array of strings. I use the code below to accomplish this, and it has been working great so far.



KCSAppdataStore *placesStore = [KCSAppdataStore storeWithOptions:@{ KCSStoreKeyCollectionName : @"places",

KCSStoreKeyCollectionTemplateClass : [Place class]}];



//if distance is 0 then it will get everything from the database.

if (useMaxDistance) {

//this is the code that gets stuff from the database that is up to a certain distance away.

geoQuery = [KCSQuery queryOnField:KCSEntityKeyGeolocation usingConditionalsForValues: kKCSNearSphere,

@[@(currentLocation.coordinate.longitude), @(currentLocation.coordinate.latitude)],

kKCSMaxDistance, @(maxDistance), nil];

} else {

//this code is for getting a query that has no distance limit

geoQuery = [KCSQuery queryOnField:KCSEntityKeyGeolocation

usingConditional:kKCSNearSphere

forValue:@[@(currentLocation.coordinate.longitude), @(currentLocation.coordinate.latitude)]];

}



//setup the compound query

channelQuery = [KCSQuery queryOnField:@"channels" withRegex:channelName];

mutiQuery = [[KCSQuery alloc] init];

[mutiQuery addQuery:geoQuery];

[mutiQuery addQuery:channelQuery];





So as you can see I do this by using a regex with just the channelName. channelName is a string. The issue I am having right now is i need to match two strings now. So not only do I need to geocde but I also want to match channelName on that array of strings called channels but also want to match secondChannel as well on the array of strings. I know I can do this with a regex but I do not know enough about them to figure it out. I have tried this code though but it does not work:



KCSAppdataStore *placesStore = [KCSAppdataStore storeWithOptions:@{ KCSStoreKeyCollectionName : @"places",

KCSStoreKeyCollectionTemplateClass : [Place class]}];



//if distance is 0 then it will get everything from the database.

if (useMaxDistance) {

//this is the code that gets stuff from the database that is up to a certain distance away.

geoQuery = [KCSQuery queryOnField:KCSEntityKeyGeolocation usingConditionalsForValues: kKCSNearSphere,

@[@(currentLocation.coordinate.longitude), @(currentLocation.coordinate.latitude)],

kKCSMaxDistance, @(maxDistance), nil];

} else {

//this code is for getting a query that has no distance limit

geoQuery = [KCSQuery queryOnField:KCSEntityKeyGeolocation

usingConditional:kKCSNearSphere

forValue:@[@(currentLocation.coordinate.longitude), @(currentLocation.coordinate.latitude)]];

}



//setup the compound query

//setup the compound query

channelQuery = [KCSQuery queryOnField:@"channels" withRegex:channelName];

mutiQuery = [[KCSQuery alloc] init];

[mutiQuery addQuery:geoQuery];

[mutiQuery addQuery:channelQuery];



if (![secondChannel isEqualToString:ALLPLACES] && secondChannel != NULL) {

channelQuery = [KCSQuery queryOnField:@"channels" withRegex:secondChannel];

[mutiQuery addQuery:channelQuery];

}



Any ideas on how I can set up the regex for the first channelQuery to incorporate both strings secondChannel and channelName in the query?



thanks,

Sean


As for building the regualur expression I came up with some ideas that I thought would work but for soem reason kinvey's database calls are returning nothing. Here is the regular expression I was thinking about using:



(firstChannel.+?secondChannel)|(secondChannel.+?firstChannel)



But like I said kinvey is returning nothing no the call. Any ideas?
Here is a follow up to this question that explains it a bet better and also has a couple of different ways of trying this.



I am going to detail the 3 ways I have tried to do this. I am trying to geocode AND search on "channels"(Array of strings) for channelOne(String) AND search on "channels"(Array of strings) for channelTwo(String).



This is what I think the problem is. I am trying to use a regex to query an array of strings. I am expecting the array of strings to be represented by "["channel1", "channel2", "channel3"]" If this is the case then I can use a regular expression that will take this "string" (that is an array of the strings in the backend) and evaluate it to find a match for a channel AND anotherChannel. This is the code:



//need to setup the regular expression

NSError *error = NULL;

NSString *placeHolder = @"(%@.+?%@)|(%@.+?%@)";

NSString *pattern = [NSString stringWithFormat:placeHolder, channelName, secondChannel, secondChannel, channelName];



NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];



if (error) {

NSLog(@"Couldn't create regex with given string and options.");

}



//setup the compound query

channelQuery = [KCSQuery queryOnField:@"channels" withRegex:regex];

mutiQuery = [[KCSQuery alloc] init];

//[mutiQuery addQuery:geoQuery];

//[mutiQuery addQuery:channelQuery];



This is breaking. It returns results that are not related to the search. I am not sure what the problem is. The regular expression works fine in the regular expression testers. But again the problem with this is I do not no if you guys(kinvey) are loading the array of strings into an array and then evaluating the expression or if you are loading the value of the array into a string and evaluating the expression.





This is not working as expected. So I tried to create two queries and add them with the add query function. The function I am using is:

[kinveyQuery addQuery:secondQuery];

but this is not working either. I am getting nothing back. firstChannel and secondChannel are just simple strings to search on. Here is the code:



channelQuery = [KCSQuery queryOnField:@"channels" withRegex:firstChannel];

secondChannelQuery = [KCSQuery queryOnField:@"channels" withRegex:secondChannel];

mutiQuery = [[KCSQuery alloc] init];

[mutiQuery addQuery:geoQuery];

[mutiQuery addQuery:secondChannelQuery];

[mutiQuery addQuery:channelQuery];



This returns nothing at all. I have tried to remove the geoquery and it is still not working. If I remove the secondChannelQuery query it works fine. Meaning if it is just the geoquery and the channelQuery it works fine.



The third way I tried to do this is using the function [KCSQuery queryForJoiningOperator:onQueries:] as detailed here http://devcenter.kinvey.com/ios/guides/datastore#CompoundQueries . Here is the code:



mutiQuery = [KCSQuery queryForJoiningOperator:kKCSAnd onQueries:geoquery, channelQuery, secondChannelQuery, nil];



This one returned from the database saying that the Kinvey server errored.



Is this even possible? Any ideas on what is going on. Thanks for any help anyone can give on this.



Thanks,

Sean
Hi Sean,



If the channels field is an array the regex should still work. I am not sure yet if you can do two regexs on the same field, however. I wouldn't expect mongo to support the advanced regexs, but I am not sure. I will have to look into this a bit more and get back to you.
Do you have any creative ways that this may be accomplished? Or do you think how I am coming at it is pretty much the way to tackle it?
Is there any update on this?? I am still needing to be able to do a dual query and geolocate it.
Still no way to have a triple query?
Login or Signup to post a comment