如何在 Realm 中查找孤立的列表项
How to Find Orphaned List Items in Realm
假设我有一个 Realm 架构,其中有一个 parent class 和 List
下面的孩子。像这样:
class Parent: Object{
@objc dynamic var name = ""
let kids = List<Kid>()
}
class Kid: Object{
@objc dynamic var name = ""
}
假设,随着时间的推移,每当 Kid
被删除时,它只会从 Parent
object 中删除,而不会从 Realm 中删除:
let realm = try! Realm()
let parent = realm.objects(Parent.self)
realm.beginWrite()
for kid in parent.kids{
if let index = parent.kids.index(of: kid){
parent.kids.remove(at: index)
}
}
try! realm.commitWrite()
我知道我可以在与从 parent
中删除相同的写入事务中从 Realm 中删除 kids
:
let kids = parent.kids
realm.delete(kids)
...但我有理由不这样做。
有没有办法在 Realm 数据库中查询不属于 parent
的所有 kids
?例如,如果你打开我的 Realm,你可以看到 100
kid
object,但是如果你查看 parent,只有 5
的 kid
object 实际上附加到 parent
object.
我有一个 Realm 的特殊用例,我实际上不想删除 child List
项,除非我知道它们没有 parent。是否可以查询所有 parentless kid
的领域?
除非您使用 LinkingObjects,否则无法直接 parents 查询孩子的领域。如果现在更改数据模型还为时不晚,那么我建议使用它们。
class Parent: Object{
@objc dynamic var name = ""
let kids = List<Kid>()
}
class Kid: Object{
@objc dynamic var name = ""
let parents = LinkingObjects(fromType: Parent.self, property: "kids")
}
当您将 Kid
添加到 Parent.kids
领域时,系统会自动为您处理 Kid.parents
关系。当你删除一个 Parent
时,Kid.parents
将是空的(假设 Kid
只有一个 Parent
)。 LinkingObjects
的好处在于您可以将它们合并到您的查询中。所以要找到所有 Kid
object 没有 parents 的查询将是:
func fetchKidsWithoutParents1() -> Results<Kid> {
let realm = try! Realm()
return realm.objects(Kid.self).filter("parents.@count == 0")
}
如果不使用LinkingObjects
,则必须查询所有Kid
object和所有Parent
object,看看是否Kid
存在于任何 Parent.kids
List
中。这种方法有两个缺点。首先是所有 Kid
object 都将在您手动过滤时加载到内存中。另一个是您无法利用领域通知,因为生成的孩子不会存储在领域 Result
object 中。请注意,以下示例假定没有两个 Kid
object 具有相同的名称:
func fetchKidsWithoutParents2() -> [Kid] {
let realm = try! Realm()
let kids = realm.objects(Kid.self)
let parents = realm.objects(Parent.self)
return kids.filter { kid in
parents.filter("SUBQUERY(kids, $kid, $kid.name == %@).@count > 0", kid.name).count == 0
}
}
这个问题是
Is there a way to query the Realm database for all kids that don't
belong to a parent?
好的!一行代码超级简单
let results = realm.objects(Parent.self).filter("ANY kids == %@", thisKid)
当然有,评价一下有没有结果
if results.count == 0 {
print("kid: \(thisKid?.name) has no parents.")
} else {
print("found parents for kid: \(thisKid?.name)")
for kid in results {
print(kid)
}
}
编辑:
在上面的代码中,您可以遍历每个孩子,看看它是否有 parent,如果没有,则将其删除。作为一个挑战,一些代码将删除所有没有 parent 的孩子而不是迭代怎么样。 allKids 是一个领域列表。
let foundParents = realm.objects(Parent.self).filter("ANY kids IN %@", allKids)
let kidsThatHaveParents: [Kid] = allKids.compactMap { kid in
let x = foundParents.first { [=12=].kids.contains( kid ) }
if x != nil { //this is just for clarity, could be shortened
return kid
}
return nil
}
let haveParentSet = Set(kidsThatHaveParents)
let kidsToCheckSet = Set(allKids)
let kidsToRemove = kidsToCheckSet.subtracting(haveParentSet)
这样做的一个缺点是我使用了一个集合来减去有 parent 的孩子。这将把所有的孩子加载到内存中,绕过领域的延迟加载方面。另一种选择是从 kidsToLook for realm 列表中删除每个具有 parent 的孩子。
假设我有一个 Realm 架构,其中有一个 parent class 和 List
下面的孩子。像这样:
class Parent: Object{
@objc dynamic var name = ""
let kids = List<Kid>()
}
class Kid: Object{
@objc dynamic var name = ""
}
假设,随着时间的推移,每当 Kid
被删除时,它只会从 Parent
object 中删除,而不会从 Realm 中删除:
let realm = try! Realm()
let parent = realm.objects(Parent.self)
realm.beginWrite()
for kid in parent.kids{
if let index = parent.kids.index(of: kid){
parent.kids.remove(at: index)
}
}
try! realm.commitWrite()
我知道我可以在与从 parent
中删除相同的写入事务中从 Realm 中删除 kids
:
let kids = parent.kids
realm.delete(kids)
...但我有理由不这样做。
有没有办法在 Realm 数据库中查询不属于 parent
的所有 kids
?例如,如果你打开我的 Realm,你可以看到 100
kid
object,但是如果你查看 parent,只有 5
的 kid
object 实际上附加到 parent
object.
我有一个 Realm 的特殊用例,我实际上不想删除 child List
项,除非我知道它们没有 parent。是否可以查询所有 parentless kid
的领域?
除非您使用 LinkingObjects,否则无法直接 parents 查询孩子的领域。如果现在更改数据模型还为时不晚,那么我建议使用它们。
class Parent: Object{
@objc dynamic var name = ""
let kids = List<Kid>()
}
class Kid: Object{
@objc dynamic var name = ""
let parents = LinkingObjects(fromType: Parent.self, property: "kids")
}
当您将 Kid
添加到 Parent.kids
领域时,系统会自动为您处理 Kid.parents
关系。当你删除一个 Parent
时,Kid.parents
将是空的(假设 Kid
只有一个 Parent
)。 LinkingObjects
的好处在于您可以将它们合并到您的查询中。所以要找到所有 Kid
object 没有 parents 的查询将是:
func fetchKidsWithoutParents1() -> Results<Kid> {
let realm = try! Realm()
return realm.objects(Kid.self).filter("parents.@count == 0")
}
如果不使用LinkingObjects
,则必须查询所有Kid
object和所有Parent
object,看看是否Kid
存在于任何 Parent.kids
List
中。这种方法有两个缺点。首先是所有 Kid
object 都将在您手动过滤时加载到内存中。另一个是您无法利用领域通知,因为生成的孩子不会存储在领域 Result
object 中。请注意,以下示例假定没有两个 Kid
object 具有相同的名称:
func fetchKidsWithoutParents2() -> [Kid] {
let realm = try! Realm()
let kids = realm.objects(Kid.self)
let parents = realm.objects(Parent.self)
return kids.filter { kid in
parents.filter("SUBQUERY(kids, $kid, $kid.name == %@).@count > 0", kid.name).count == 0
}
}
这个问题是
Is there a way to query the Realm database for all kids that don't belong to a parent?
好的!一行代码超级简单
let results = realm.objects(Parent.self).filter("ANY kids == %@", thisKid)
当然有,评价一下有没有结果
if results.count == 0 {
print("kid: \(thisKid?.name) has no parents.")
} else {
print("found parents for kid: \(thisKid?.name)")
for kid in results {
print(kid)
}
}
编辑:
在上面的代码中,您可以遍历每个孩子,看看它是否有 parent,如果没有,则将其删除。作为一个挑战,一些代码将删除所有没有 parent 的孩子而不是迭代怎么样。 allKids 是一个领域列表。
let foundParents = realm.objects(Parent.self).filter("ANY kids IN %@", allKids)
let kidsThatHaveParents: [Kid] = allKids.compactMap { kid in
let x = foundParents.first { [=12=].kids.contains( kid ) }
if x != nil { //this is just for clarity, could be shortened
return kid
}
return nil
}
let haveParentSet = Set(kidsThatHaveParents)
let kidsToCheckSet = Set(allKids)
let kidsToRemove = kidsToCheckSet.subtracting(haveParentSet)
这样做的一个缺点是我使用了一个集合来减去有 parent 的孩子。这将把所有的孩子加载到内存中,绕过领域的延迟加载方面。另一种选择是从 kidsToLook for realm 列表中删除每个具有 parent 的孩子。