CoreData 对多对多关系进行排序

发布于 2024-10-15 21:59:19 字数 784 浏览 2 评论 0原文

我正在编写一个 iOS 应用程序,其中存储了人员记录,并且需要显示以特定方式排序的列表。这些订单的数量是可变的,并且它们是动态生成的,但我希望它们存储在数据存储中。执行此操作的 SQL 方法是创建一个 ListPositions 表,其中包含列表名称、persons 表中的 id 和排序键。然后,为了显示特定列表,我可以选择具有给定名称的所有列表 ListPosition,拉入引用的人员,然后按排序键进行排序。尝试在 CoreDatat 中执行此操作,但遇到了问题。我尝试使用如下模式来执行此操作:

Person:
    Name
    DOB
    etc... 
    positions -->> ListPosition

ListPosition:
    listName
    sortKey
    person --> Person

然后,我可以使用 NSPredicate 获取给定列表中的所有人员 [NSPredicate predicateWithFormat:@"ANY Positions.listName like %@", someList]; 这允许我动态添加针对大量人员的列表。问题是我无法使用 ListPosition 的 sortKey 字段对人员进行排序。什么 NSSortDescriptor 会执行此操作?如果无法对一对多关系的一个元素的属性的获取进行排序,那么在 coredata 中获取多个动态排序的另一种方法是什么?我使用 NSFetchedResultsController 显示列表,因此我无法自己将列表放在内存中。我需要用一个 NSFetchRequest 来完成它。

I'm writing an iOS app which has store of person records, and needs to display lists them sorted in particular ways. There are a variable number of these orderings, and they are generated on the fly, but I would like them to be stored in the datastore. The SQL way to do this is to have a ListPositions table with a list name, an id into the persons table, and a sort key. Then, to display a particular list, I can select all list ListPositions with a given name, pull in the referenced persons, and sort on the sort key. Trying to do this in CoreDatat, however I run into problems. I am trying to do this using a schema like:

Person:
    Name
    DOB
    etc... 
    positions -->> ListPosition

ListPosition:
    listName
    sortKey
    person --> Person

Then, I can get all the Persons in a given list with the NSPredicate
[NSPredicate predicateWithFormat:@"ANY positions.listName like %@", someList];
This allows me to dynamically add lists against a large set of Persons. The problem is that I am unable to use the sortKey field of ListPosition to sort the Persons. What NSSortDescriptor will do this? And if it is not possible to sort a fetch on the property of one element of a to-many relationship, what is another way to get multiple, dynamic orderings in coredata? I am displaying the lists with a NSFetchedResultsController, so I can't put the lists together myself in memory. I need to do it with a single NSFetchRequest.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我一直都在从未离去 2024-10-22 21:59:19

你是对的——遵循一对多关系会返回一个 NSSet,它没有固有的排序。要获得排序结果,有几个选项:

  1. 假设 Person/ListPosition 是双向关系,对 ListPosition 实体执行新的获取请求。使谓词匹配 ListPosition 中的“person”关系,类似于 [NSPredicate predicateWithFormat:@"person=%@", myPerson]。在获取请求中使用您需要的任何排序描述符。
  2. 遵循您正在做的关系,这将为您提供一个 NSSet。然后使用 NSSet 的 -sortedArrayUsingDescriptors: 方法将其转换为排序数组。

You're right-- following a to-many relationship returns an NSSet, which has no inherent sorting. To get sorted results there are a couple of options:

  1. Assuming that Person/ListPosition is a two-way relationship, do a new fetch request for ListPosition entities. Make the predicate match on the "person" relationship from ListPosition, which would look something like [NSPredicate predicateWithFormat:@"person=%@", myPerson]. Use whatever sort descriptor you need on the fetch request.
  2. Follow the relationship as you're doing, which gives you an NSSet. Then use NSSet's -sortedArrayUsingDescriptors: method to convert that to a sorted array.
守望孤独 2024-10-22 21:59:19

我认为在这种情况下最好的方法是获取 ListPosition 实体。添加 sortKey 的排序描述符(在这种情况下它会起作用,因为获取请求位于 ListPosition 实体上),并在获取请求上使用 setRelationshipKeyPathsForPrefetching for “person” 预获取与列表名称关联的 Person。

[NSPredicate predicateWithFormat:@"listName like %@", someList];

I think the best approach in this case would be to fetch on ListPosition entity instead. Add the sort Descriptor for sortKey (it would work in this case because the fetch request is on ListPosition entity) and prefetch the Person associated with the the list name using setRelationshipKeyPathsForPrefetching for "person" on the fetch request.

[NSPredicate predicateWithFormat:@"listName like %@", someList];
娇女薄笑 2024-10-22 21:59:19

如果我正确理解您的模型,则每个 Person 对于其参与的每个列表都有一个 ListPosition。假设我们有按姓名升序排列的列表,因此 X 个人有 X 个具有相同 listNamesortKey 的列表位置。

我将创建实体 List,其中包含 sortKey 属性,然后在排序描述符中使用它。

entity List:
    - sortKey : string
    - ascending : bool

创建排序描述符并在获取请求中使用它:

[NSSortDescriptor sortDescriptorWithKey:chosenList.sortKey ascending:chosenList.ascending];

然后您可以拥有任意数量的列表,并且您可以轻松地使用其排序键对所有人员进行排序。


如果您想将位置存储在数据库中(您没有在 ListPosition 中提到属性 index 或类似的内容),您可以创建“联合实体”:

entity PersonInList:
    - index : integer
    - person -> Person
    - list –> List

另一个想法直接在 List 实体中订购了一组 Person 对象。

If I understand your model correctly, each Person has one ListPosition for each list in which it participates. Let's say we have acsending list by their names, so X people have X list positions with the same listName and sortKey.

I would create entity List, that would contain the sortKey attribute and then use it in sort descriptor.

entity List:
    - sortKey : string
    - ascending : bool

Create sort descriptor and use it in fetch request:

[NSSortDescriptor sortDescriptorWithKey:chosenList.sortKey ascending:chosenList.ascending];

Then you may have as many Lists as you want and you can easily use its sort key to sort all people.


If you want to store the positions in database (you didn't mention attribute index in your ListPosition, or anything similar), you can create “joint entity”:

entity PersonInList:
    - index : integer
    - person -> Person
    - list –> List

Another idea is having ordered set of Person objects directly in List entity.

疧_╮線 2024-10-22 21:59:19

获取 ListPosition(它将作为 NSMutableSet 出现)。然后对 Set 进行排序,如下所示:

NSMutableSet *positionsSet = [personEntity mutableSetValueForKey:@"positions"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"yourSortKey" ascending:NO];
NSArray *positionsSortedSet = [positionsSet sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

这将根据您的键为您提供一个排序后的数组。

Get the ListPosition (it will come as a NSMutableSet). Then do a sort on the Set, like this:

NSMutableSet *positionsSet = [personEntity mutableSetValueForKey:@"positions"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"yourSortKey" ascending:NO];
NSArray *positionsSortedSet = [positionsSet sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

That will give you a sorted out array according to your key.

极度宠爱 2024-10-22 21:59:19

我通常向实体添加索引字段(类型 NSNumber)。添加项目时计算索引非常容易。这样

object.index = person.positions.count

,实际上您不需要职位字段,而是职位关系。将 person 实体连接到 ListPosition 实体就足够了。

I usually add an index field (type NSNumber) to an entity. It's very easy to calculate index in adding item. just by

object.index = person.positions.count

so, actually you don't need positions field but positions relationship. connect person entity to ListPosition entity would be enough.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文