Stackmob SMQuery OR conditioning: "Sort cannot be used with OR statements stackmob" - stackmob

I am using Stackmob SMQuery and trying to have a Query with 4 OR conditions and sort all the results after all. My code is as below. The problem is
SMQuery *query = [[SMQuery alloc] initWithSchema:STACKMOB_SCHEMA_TESTIMONIAL];
[query where:#"friend_id" isIn:[friendFacebookIds arrayByAddingObject:[KKKeychain getStringForKey:#"facebookId"]]];
// WHERE (privacy == Public OR (privacy == Private AND friend_id == myFacebookId) OR (privacy == Restricted AND myFacebookId NOT IN restricted_Ids))
SMQuery *subQuery0 = [[SMQuery alloc] initWithSchema:STACKMOB_SCHEMA_TESTIMONIAL];
SMQuery *subQuery1 = [[SMQuery alloc] initWithSchema:STACKMOB_SCHEMA_TESTIMONIAL];
SMQuery *subQuery2 = [[SMQuery alloc] initWithSchema:STACKMOB_SCHEMA_TESTIMONIAL];
SMQuery *subQuery3 = [[SMQuery alloc] initWithSchema:STACKMOB_SCHEMA_TESTIMONIAL];
[subQuery0 where:#"privacy" isEqualTo:nil]; // just in case no privacy was set, assume it is public
[subQuery0 orderByField:#"createddate" ascending:NO];
[subQuery1 where:#"privacy" isEqualTo:[NSNumber numberWithInt:TTPrivacyLevelPublic]];
[subQuery1 orderByField:#"createddate" ascending:NO];
[subQuery2 where:#"privacy" isEqualTo:[NSNumber numberWithInt:TTPrivacyLevelPrivate]];
[subQuery2 where:#"user_id" isEqualTo:[KKKeychain getStringForKey:#"facebookId"]]; // for private post, I can only see posts that were created by me
[subQuery2 orderByField:#"createddate" ascending:NO];
[subQuery3 where:#"privacy" isEqualTo:[NSNumber numberWithInt:TTPrivacyLevelRestricted]];
[subQuery3 where:#"restricted_user_ids" isNotEqualTo:[KKKeychain getStringForKey:#"facebookId"]]; // make sure I'm not restricted to see
[subQuery3 orderByField:#"createddate" ascending:NO];
// combine subquery to main query
[query and:[[[subQuery1 or:subQuery2] or:subQuery3] or:subQuery0]];
[query orderByField:#"createddate" ascending:NO];
....
So if I commented the last line "[query orderByField:#"createddate" ascending:NO];" then it works fine. But then the results will be a combination of 4 different dataset which is not sorted in createdate order. I also tried to sort in each subquery but the result was also incorrect because they are only sorted inside each subquery, not combining with other results as well.
Thanks.

The database doesn't support executing a query that includes both OR and sorting - this is a database limitation. Instead, perform the query on StackMob, then locally sort the results by createddate using sortedArrayUsingComparator or something similar.

Related

a predicate to filter out similar objects by an attribute

I"m performing a regular NSFetchRequest without any predicate to fetch 100 managed objects (flights), each Flight entity has an attribute of type NSString named (flightCode) and this attribute is not unique, so 2 flight objects may have the same flightCode .
However, I want to fetch all flight objects filtering out flights that have the same flightCode by taking only one flight from similarities, i.e.
if the fetch request returned 5 flights as follows:
flight1: flightCode = ABC
flight2: flightCode = AA
flight3: flightCode = ABC
flight4: flightCode = ABC
flight5: flightCode = DEF
then the fetch request must filter out any two of the 3 flights that have the flightCode ABC and take only any random one of these 3.
what is the required NSPredicate for this filtering ?
p.s. flights: 1, 3 & 4 may be different in other attributes, i.e. flight1's name may be different from flight3's name.
thanks in advance.
If you just want a list of all distinct flight codes, this may do what you want:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Flight"
inManagedObjectContext:moc];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entity.name];
request.resultType = NSDictionaryResultType;
request.returnsDistinctResults = YES;
request.propertiesToFetch = #[ entity.propertiesByName[#"flightCode"] ];
Note that returnsDistinctResults only works if propertiesToFetch is set, and propertiesToFetch only works if resultType is NSDictionaryResultType.
REVISED
If you want full Flight objects, but only one for each distinct flight code, I don't think you can do that directly. Perhaps you can ask for both the object ID and the flight code, group by flight code, and take the minimum object ID, to get one object ID for each flight code. Then you can turn those object IDs into full objects one by one using objectForID: on the managed object context. I would try something like this:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Flight"
inManagedObjectContext:moc];
NSExpressionDescription *objectIDProperty = [[NSExpressionDescription alloc] init];
objectIDProperty.name = #"objectID";
objectIDProperty.expression = [NSExpression expressionForFunction:#"min:"
arguments:#[ [NSExpression expressedForEvaluatedObject] ]];
objectIdProperty.expressionResultType = NSObjectIDAttributeType;
NSAttributeDescription *flightCodeProperty = entity.propertiesByName[#"flightCode"];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entity.name];
request.resultType = NSDictionaryResultType;
request.returnsDistinctResults = YES;
request.propertiesToFetch = #[ flightCodeProperty, objectIDProperty ];
request.propertiesToGroupBy = #[ flightCodeProperty ];
I cribbed a lot of that from this answer. I have no idea if it works, or if I'm even on the right track. If it runs at all, but doesn't quite give the right output, remember that you can see the SQL it's executing by adding -com.apple.CoreData.SQLDebug 1 as a command-line argument.
youll want to make a NSMuteableArray for all of your flights and then a separate NSMuteableArray to keep track of which elements you have already seen
pseudocode:
NSMuteablearray flights
NSMuteablearray alreadySeen
for (item in flights) {
if (alreadySeen containsObject:item)
flights removeObject:item
else
alreadySeen addObject:item
}

Sort array with ÅÄÖ

I'm totally new to iPhone/OSX development and I'm trying to sort an NSMutableArray filled with objects in alphabetical order but I fail. Items starting with Å or Ä ends up with items starting with A and items starting with Ö ends up with items starting with O. I have tried different sorting methods that I have found here on Stackoverflow but none of them seems to work (for me at least)
NSSortDescriptor* stationDescriptor = [[NSSortDescriptor alloc]initWithKey:#"name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray* descriptors = [NSArray arrayWithObject:stationDescriptor];
[stations sortUsingDescriptors:descriptors];
[stations sortUsingComparator:^NSComparisonResult(Station* obj1, Station* obj2){
return [[obj1 name] localizedCaseInsensitiveCompare:[obj2 name]];
}];
Ok, progress! I have been successful in getting this to work by changing the language on the emulator to Swedish, is there any way I can get the same result when the phone is set to English? I know in C# you can send in a reference to a specific culture when sorting/comparing strings.
/Viktor
Looking at the docs for NSString gives you the answer.
You are using localizedCaseInsensitiveCompare: and the docs for this state
blah blah blah
See Also
– compare:options:range:locale:
So jumping to the docs for compare:options:range:locale: you can figure it out. You'll need something like
return [[obj1 name] compare:[obj2 name]
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [obj1 length])
locale:whateverLocaleYouWant];

Sort the list items in A to Z order

I have list of items and want to sort them in A to Z order like Contact list does. Could anyone please help me to understand how to do this? Any documentation on this would be appreaciated.
Thanks.
In order to display/arrange your data in alphabetical order which in a array you have to use NSSortDescriptorthere is a core data tutorial in the devlopers document of X-Code and here it is coreDataBooks and its a best one try to take help from there see how they are displaying the data in alphabetical order also refer here.
NSSortDescriptor *sortByName= [[NSSortDescriptor alloc] initWithKey:#"self" ascending:NO selector:#selector(compareName:)];
if(sortByName)
{
[yourArray sortUsingDescriptors:[NSArray arrayWithObject:sortByName]];
[sortByUnlockLevel release];
}
And in your modal implement the method compareName
- (NSComparisonResult)compareName:(id)inObject
{
NSComparisonResult result = NSOrderedSame;
result = [Object.mName compare:self.mName];
return result;
}

Query two and more song at one time using the function "addFilterPredicate" by MPMediaItemPropertyPersistentID

My app loads a music playlist automatically when it starts up. In order to do this, I store the song IDs MPMediaItemPropertyPersistentID to a database, and load the songs when the app is starting up next time. The main code is the following:
MPMediaQuery *MPMediaSongQuery = [MPMediaQuery songsQuery];
MPMediaPropertyPredicate *iPodMusicSongPredicateiPodMusicSongPredicate = [MPMediaPropertyPredicate
predicateWithValue:[NSNumber numberWithUnsignedLongLong: songID]
forProperty:MPMediaItemPropertyPersistentID
comparisonType:MPMediaPredicateComparisonEqualTo];
[MPMediaSongQuery addFilterPredicate:iPodMusicSongPredicate];
NSArray *collections = MPMediaSongQuery.collections;
The code loads song one by one. My question is: is there any way to query two or more songs by MPMediaItemPropertyPersistentID at one time when using the function addFilterPredicate:? Thanks.
If you use more than one addFilterPredicate they are combined with a logical AND. So you canm only reduce the results of the first query, but not extend it. As a consequence you are not allowed to use several addFilterPredicates for the same property. In fact the result is undefined and most likely will end up in an empty collection. What you are looking for is a combination of the same property with a logical OR. You can achieve this like depicted in the following pseudo-code:
MPMediaQuery *MPMediaSongQuery = [MPMediaQuery songsQuery];
NSMutableArray *collections = [[NSMutableArray alloc] initWithCapacity:1];
for (int i=0; i < songIDCount; i++) {
MPMediaPropertyPredicate *iPodMusicSongPredicateiPodMusicSongPredicate = [MPMediaPropertyPredicate
predicateWithValue:[NSNumber numberWithUnsignedLongLong: songID[i]]
forProperty:MPMediaItemPropertyPersistentID
comparisonType:MPMediaPredicateComparisonEqualTo];
[MPMediaSongQuery addFilterPredicate:iPodMusicSongPredicate];
[collections addObjectsFromArray:MPMediaSongQuery.collections];
[MPMediaSongQuery removeFilterPredicate:iPodMusicSongPredicate];
}
...

How to implement TouchXml Parser?

I have implemented demo using TouchXml parser.Its working fine.But I want to parse xml like below.
example:
<Root>
<tag1></tag1>
<tag2>
<temp1></temp1>
<temp2></temp2>
<temp3></temp3>
</tag2>
<tag3></tag3>
</Root>
How to parse this type of example?
TouchXML is nice and easy to use. First you'll want to parse the document:
NSError *theError = NULL;
CXMLDocument *theXMLDocument = [[[CXMLDocument alloc] initWithXMLString:input options:0 error:&theError] autorelease];
You can then query the structure of your document using XPath. For example to extract the Root element you might do this:
NSArray *foundRoots = [theXMLDocument nodesForXPath:#"//Root" error:&theError];
CXMLElement *root = [foundRoots objectAtIndex:0];
(You often get arrays back, so in your case you can just take the first element, assuming it exists in the document)
You can also do things like get all the child elements of an element. So if we wanted to get all the tags we could this:
NSArray *children = [root children];
Or we could get a tag with a particular name:
NSArray *tag1 = [root elementsForName:#"tag1"];
(Again you get an array, so do the right thing and check)
Does your data conform to any schema?