多对多关系如何运作。
Posted
技术标签:
【中文标题】多对多关系如何运作。【英文标题】:How does many to many relationships work. 【发布时间】:2017-04-15 01:08:58 【问题描述】:好的,我已经阅读了苹果Core Data Guide。我也在网上看,但只找到大约 2 年前的帖子。所以我不知道有多少关系有效。我正在使用核心数据构建应用程序。该应用有 3 个实体 Pokemon、Type、Ability强>。口袋妖怪可以有一种或多种类型,所以我将关系设置为多。一个类型可以有多个与之关联的口袋妖怪,所以我也应该将关系设置为多对多,但我不理解多对多关系。能力也是一样。这就是我的数据模型的样子。还有另外 2 个实体,但我现在并不真正关心这些。
这是我用来解析以下API 的函数。它获取前 20 个 Pokemon 保存名称并使用 url 获取有关该 Pokemon 的更多信息。所以我添加了另一个任务,为那个口袋妖怪添加类型和能力。
private func loadPokemon(url: String)
let context = coreData.persistentContainer.viewContext
let request = URLRequest(url: URL(string: url)!)
let task = URLSession.shared.dataTask(with: request) (data, response, error) in
if error != nil
print(error!)
do
let jsonResults = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
let pokemonArray = jsonResults.value(forKey: "results") as! [[String: Any]]
for pokemonData in pokemonArray
guard let name = pokemonData["name"] as? String else
return
guard let pokemonInfoURL = pokemonData["url"] as? String else
return
let pokemon = Pokemon(context: context)
pokemon.name = name
print(1)
self.pokemonMoreInfo(for: pokemon, url: pokemonInfoURL, context: context)
catch let err
print(err.localizedDescription)
task.resume()
private func pokemonMoreInfo(for pokemon: Pokemon, url: String, context: NSManagedObjectContext)
let request = URLRequest(url: URL(string: url)!)
let task = URLSession.shared.dataTask(with: request) (data, response, error) in
if error != nil
print(error!)
do
let jsonResults = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
//MARK: Pokemon Abilities
if let abilityArray = jsonResults.value(forKey: "abilities") as? [[String: Any]]
let abilities = pokemon.ability?.mutableCopy() as! NSMutableSet
for abilityData in abilityArray
guard let abilityDic = abilityData["ability"] as? NSDictionary else
return
let name = abilityDic.value(forKey: "name") as! String
guard let isHidden = abilityData["is_hidden"] as? Bool else
return
guard let slot = abilityData["slot"] as? Int16 else
return
let ability = Ability(context: context)
ability.name = name
ability.isHidden = isHidden
ability.slot = slot
abilities.add(ability)
pokemon.addToAbility(abilities)
//MARK: Pokemon Type
if let typeArray = jsonResults.value(forKey: "types") as? [[String: Any]]
let types = pokemon.type?.mutableCopy() as! NSMutableSet
for typeData in typeArray
guard let typeDic = typeData["type"] as? NSDictionary else
return
let name = typeDic.value(forKey: "name") as! String
guard let slot = typeData["slot"] as? Int16 else
return
let type = Type(context: context)
type.name = name
type.slot = slot
types.add(type)
pokemon.addToType(types)
catch let err
print(err.localizedDescription)
self.coreData.saveContext()
task.resume()
我正在使用这个名为 SQLight Read-Only 的应用程序。能力和类型与正确的口袋妖怪匹配。这些是我的 SQLight 的截图。
我不确定你们是否知道 Pokemon,但喷火龙类型是 fire 和 flying并拥有太阳能和烈焰人的能力。所以我知道我正在正确保存数据。但是我的 SQLight 具有相同的重复类型,例如 fire、grass、poison em> 同样适用于能力,但与正确的口袋妖怪相关联。这就是我完整的 SQLight 的样子。
不确定它是否会以多对多关系重复。所以我的问题是我如何使用与 Pokemon 的多对多关系来 type 和 能力。那么如何添加具有相同类型或相同能力的口袋妖怪。所以稍后,我可以执行抓取所有具有火类型或相同能力的口袋妖怪。我不确定我是否正确解释了我的问题可能有点令人困惑。
不胜感激。 :)
【问题讨论】:
Core Data 是一个对象持久化系统,而不是一个 sql 数据库。我建议您不要尝试分析底层的 sql 数据存储。只需将对象引用设置为 Pokemon 的type
属性,然后让 CoreData 更新引用。
【参考方案1】:
编辑: 实际上,我在下面写的内容对于 Core Data 是不正确的。 (感谢您在 cmets Paulw11 中指出这一点。)来自Core Data Guide:
多对多关系
您使用二对多关系定义多对多关系。第一个多对多关系从第一个实体(源实体)到第二个实体(目标)。第二对多关系从第二个实体(原始目标实体)到第一个实体(原始源实体)。然后,您将每个设置为另一个的倒数。 (如果您有数据库管理背景并且这引起您的担忧,请不要担心:如果您使用 SQLite 存储,Core Data 会自动为您创建中间连接表。)
旧答案(Core Data 不正确): 要在关系数据库中创建多对多关系,您必须添加一个帮助表。在您的情况下,您可以将其称为 PokemonWithType。它有两列,一列用于 Pokemon id,另一列用于 Type id。如果您想查找某个特定口袋妖怪的所有类型,您只需使用特定口袋妖怪 id 查询 PokemonWithType 中的所有条目。如果您想查找所有具有特定类型的口袋妖怪,您只需使用类型 id 即可。
【讨论】:
你好本杰明,你能提供截图或示例代码吗?如果可以的话,将不胜感激。 :) CoreData 直接支持多对多关系。虽然它可以由 SQLite 支持,但它是一个对象持久性系统,而不是数据库。 是的。我更正了我的答案。 @Luis - 您需要添加从能力到口袋妖怪和从类型到口袋妖怪的多对多关系。然后应该出现所需的关系。抱歉,我现在无法提供屏幕截图。以上是关于多对多关系如何运作。的主要内容,如果未能解决你的问题,请参考以下文章