2012-11-07 22 views
5

Đối với cuộc sống của tôi, tôi dường như không thể làm được điều này.Làm cách nào để bạn xây dựng biến vị ngữ cho NSFetchRequest setHavingPredicate :?

Giả sử thực thể của chúng tôi là đối tượng được quản lý với trường trạng thái và trường đơn đặt hàng.

Tôi làm cách nào để nhận tất cả các đơn đặt hàngBài viết có nhiều đơn đặt hàng giống nhau?

Vui lòng không có câu trả lời để chỉ làm một truy vấn con với @count trong vị từ chính, vì tôi biết giải pháp đó, điểm của bài đăng này là hiểu cách sử dụng vị từ có dữ liệu cốt lõi. có thể nhanh hơn một truy vấn phụ. (trừ khi bạn giải thích lý do tại sao tôi không thể sử dụng điều khoản có)

Mã sau đây sẽ trả về một loạt từ điển có số đơn đặt hàng trên mỗi số đơn đặt hàng. Điều tôi muốn là có thể thêm mệnh đề có để hạn chế yêu cầu của tôi chỉ trả về các từ điển đại diện cho các đối tượng của những đơn hàng có số lượng lớn hơn 1.

Đây là mã cho đến nay và nỗ lực của tôi ngữ:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"OrderedEntry" 
              inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 
[fetchRequest setResultType:NSDictionaryResultType]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat: 
       @"(status == %@)",[NSNumber numberWithInt:EntryStatusAlive]]; 


[fetchRequest setPredicate:predicate]; 


NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"order"]; // Does not really matter 
NSExpression *maxExpression = [NSExpression expressionForFunction: @"count:" 
                 arguments: [NSArray arrayWithObject:keyPathExpression]]; 
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; 
[expressionDescription setName: @"orderCount"]; 
[expressionDescription setExpression: maxExpression]; 
[expressionDescription setExpressionResultType: NSInteger32AttributeType]; 

[fetchRequest setPropertiesToFetch: [NSArray arrayWithObjects:expressionDescription,@"order",nil]]; 


[fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObjects:@"order",nil]]; 
//[fetchRequest setHavingPredicate:[NSPredicate predicateWithFormat:@"@count > 1"]]; 
//[fetchRequest setHavingPredicate:[NSComparisonPredicate predicateWithLeftExpression:maxExpression rightExpression:[NSExpression expressionForConstantValue:[NSNumber numberWithInteger:1]] modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:NSCaseInsensitivePredicateOption]]; 

NSError *error; 

NSArray * array = [context executeFetchRequest:fetchRequest error:&error]; 
+1

Bạn đã bao giờ nhận được một câu trả lời về vấn đề này? Tôi đã tìm thấy nhiều tham chiếu vô ích đối với 'setHavingPredicate' không cung cấp dấu hiệu cho thấy định dạng của vị từ này cần phải là gì. Không có ví dụ làm việc, và không có gì mà tôi đã thử đã làm việc ... –

+2

@ChristopherKing Không, tôi về cơ bản đã từ bỏ, KHÔNG có thông tin trên web và các diễn đàn web của Apple không hữu ích hơn. Tôi thực sự tin rằng không ai sử dụng điều này, vì nó rất dễ dàng để xây dựng các chức năng tương tự của các Có predicate chỉ bằng cách làm một lấy bình thường và sau đó chuyển qua các dữ liệu với một bộ lọc hoặc bằng tay với một vòng lặp. Chúng tôi muốn biết bởi vì luôn có 'cách đúng đắn' để làm điều gì đó, đặc biệt nếu api được cung cấp. – thewormsterror

Trả lời

0

thứ nhất, bất cứ khi nào tôi cố gắng một cái gì đó tương tự như những gì bạn đang làm, tôi nhận được một lỗi mà bạn không thể vượt qua một mối quan hệ với nhiều người để setPropertiesToFetch:. Các NSFetchRequest documentation sao lưu này lên: "Các mô tả tài sản có thể đại diện cho các thuộc tính , một mối quan hệ hoặc một biểu thức." Vì vậy, đó là vấn đề # 1.

Vấn đề # 2 có vẻ như bạn không thể nhóm theo mối quan hệ nhiều hoặc (điều này không được nêu rõ trong tài liệu, nhưng bạn gặp lỗi tương tự và cũng có ý nghĩa).

Xóa "đơn đặt hàng" khỏi các thuộc tính cần tìm nạp. Nhóm theo thuộc tính. Sửa đổi vị từ chính của bạn để chỉ bao gồm các thuộc tính bạn nhóm theo (hoặc chỉ xóa nó). Chỉ định "thứ tự" trong vị từ có của bạn.

[fetchRequest setPropertiesToGroupBy: @[ @"???" ]]; 
[fetchRequest setHavingPredicate: [NSPredicate predicateWithFormat: @"[email protected] > 1"]]; 

Bây giờ bạn sẽ thấy yêu cầu sẽ làm việc, nhưng kết quả có thể không phải là những gì bạn đang mong đợi:

- NSArray 
    - NSDictionary { status = @"alive", orderCount = "4" } 
    - NSDictionary { status = @"alive", orderCount = "9" } 
    - NSDictionary { status = @"alive", orderCount = "2" } 
    - etc... 

NSDictionaryResultType không thực sự cung cấp cho bạn bất cứ điều gì để xác định những đối tượng bằng - nó chỉ cung cấp cho bạn các giá trị.

Vì vậy, bước tiếp theo của bạn là lấy lại ID cho các đối tượng OrderedEntry đó. Bí quyết là để include an expression mà sẽ cung cấp cho bạn trở lại NSManagedObjectID như là một chìa khóa trong mỗi từ điển.

Tôi không biết liệu điều này có thực sự cung cấp cho bạn hiệu suất được cải thiện hay không (chỉ cần AND-ing vào vị từ chính). Theo kinh nghiệm của tôi, một trong những điều tốt nhất bạn có thể làm để cải thiện hiệu suất tìm nạp là tạo ra các NSPredicates đơn và sử dụng các biến thay thế để thiết lập mỗi lần tìm nạp. Phân tích dự đoán có thể tốn kém.

Loại kết quả từ điển có thể là một nỗi đau. Thường chỉ xây dựng một vị từ tốt là tốt hơn. Tôi chỉ có xu hướng sử dụng chúng cho các biểu thức (tức là thực hiện các phép tính kiểu thống kê trên biểu đồ trả về một giá trị). Nếu bạn xem xét tất cả các hạn chế xung quanh các thuộc tính để tìm nạp và nhóm theo và các hạn chế về vị từ, điều này dường như là những gì Apple dự định.Tôi thậm chí không chắc chắn rằng nó có thể làm những gì bạn muốn làm bằng cách nhóm và sử dụng một vị ngữ - ví dụ, bạn sẽ nhóm gì? Nếu theo trạng thái (mà bạn cần để nhóm theo để bao gồm trong vị ngữ của bạn), sẽ không làm sụp đổ tất cả các OrderEntries và bạn sẽ không nhận được các objectIDs và orderCounts riêng biệt? Tốt nhất là nên dính vào vị từ chính, không phải nhóm và có các biến vị ngữ.

+0

Tôi không hiểu bạn đang nói gì, setPropertiesToFetch: Tôi đang làm gì sai ở đây? Tôi có một thuộc tính "order" và expressionDescription là một biểu thức. – thewormsterror

+0

cho vấn đề số 2 đơn hàng của tôi là một thuộc tính, không phải là một mối quan hệ, vì vậy tôi có thể nhóm theo nó từ sự hiểu biết của tôi. – thewormsterror

+0

Làm thế nào để bạn mong đợi để đếm một thuộc tính, sau đó? thứ tự phải là mối quan hệ nhiều với ví dụ của bạn ở trên để có ý nghĩa gì cả. – karwag

1

tôi đã kết thúc đi với điều này cho bất cứ ai quan tâm đến

-(BOOL)ordersAreSaneOnDay:(NSNumber*)dayNumber forUser:(User*)user inContext:(NSManagedObjectContext*)context { 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"BasicEntry" 
              inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 
[fetchRequest setResultType:NSDictionaryResultType]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat: 
       @"(status == %@) && ((type != %@) && (type != %@) && (dayNumber == %@)) && ((user == NIL) || (user == %@))",[NSNumber numberWithInt:EntryStatusAlive],[NSNumber numberWithInt:EntryTypeTask],[NSNumber numberWithInt:EntryTypeCompletedTask],dayNumber,user]; 


[fetchRequest setPredicate:predicate]; 


NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"order"]; // Does not really matter 
NSExpression *maxExpression = [NSExpression expressionForFunction: @"count:" 
                 arguments: [NSArray arrayWithObject:keyPathExpression]]; 
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; 
[expressionDescription setName: @"orderCount"]; 
[expressionDescription setExpression: maxExpression]; 
[expressionDescription setExpressionResultType: NSInteger32AttributeType]; 

[fetchRequest setPropertiesToFetch: [NSArray arrayWithObjects:expressionDescription,@"order",nil]]; 
[expressionDescription release]; 

[fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObjects:@"order",nil]]; 
//[fetchRequest setHavingPredicate:[NSPredicate predicateWithFormat:@"[email protected] > 1"]]; 
//[fetchRequest setHavingPredicate:[NSComparisonPredicate predicateWithLeftExpression:maxExpression rightExpression:[NSExpression expressionForConstantValue:[NSNumber numberWithInteger:1]] modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:NSCaseInsensitivePredicateOption]]; 

NSError *error; 

NSArray * array = [context executeFetchRequest:fetchRequest error:&error]; 
array = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"orderCount > 1"]]; 
//NSLog(@"it worked %@",array); 
[fetchRequest release]; 

if ([array count]) return FALSE; 
return TRUE; 

}

Các vấn đề liên quan