【发布时间】:2010-10-17 12:59:39
【问题描述】:
如果您的答案与 Java / SQLite 无关,我很乐意阅读。
环境
我使用以下方案将项目存储在数据库中:
###################
# Item #
###################
# _id # This is the primary key
# parent_id # If set, it the ID of the item containing this item
# date # An ordinary date
# geocontext_id # Foreign key to a pair of named coordinates
###################
###################
# Geocontext #
###################
# _id # This is the primary key
# name # Way for the user to label a pair of coordinates (e.g : "home", "work")
# x # One of the coordinate
# y # The other one
###################
问题
我必须根据地理上下文和日期过滤项目。如果项目都在同一级别,这将是一件容易的事,但诀窍是它是递归的。例如:
root
|_item 1
|_item 2
| |_item 4
| |_item 5
| |_item 6
|_item 3
| |_item 8
| |_item 10
|_item 11
| |_item 12
|_item 7
递归深度没有明确的限制。
现在,如果我们在任何节点中并使用日期“4 月 1 日”进行过滤,我们不仅必须看到与日期匹配的节点中直接包含的项目,而且 我们必须看到包含与日期匹配的项目。
E.G : 我们在“Items 2”中,如果“item 6”匹配日期,那么我们认为“item 5”也匹配日期,我们必须保留它。如果我们在根目录,则必须显示第 2 项。
地理上下文也是如此,但更难,因为:
- 它存储在另一个表中。
- 匹配上下文是一项昂贵的数学计算。
当然,强制匹配会导致软件运行缓慢并且用户体验非常差。
注意:我不需要显示树。我从树中显示过滤数据的列表。我们必须只看到顶级元素的平面列表。挑战在于根据所有子层级决定是否显示每个元素。
我是如何解决的
我想我可以通过使用更多的表来缓存平面数据来缓解这个问题:
###################
# Geocontex_cache #
###################
# item_id # I can Join the items table on this field
# child_id # I can delete / update a child, and so delete / update the cache
# geocontext_id # I can delete / update a geocontext, and so delete / update the cache
# x # Here, I can brute force :-)
# y #
###################
###################
# Date_cache #
###################
# item_id #
# child_id #
# date #
###################
这似乎是合理的,但我还没有尝试过。不过,它应该有以下缺点:
我将昂贵的过程转移到了 /set/create/delete 方法 将不得不管理缓存的日期。 这将是一个麻烦的代码 编写和维护。五深 级别项目将触发一个过程 将递归地命中五个父母。
数据库的大小可以 变得巨大。五层深度 项目存储缓存数据为五个 父母。不知道有没有关系 因为这是一个单用户应用程序 手动输入。我不认为任何人 将插入超过 1000 个项目 深度超过 10 级。
现在好消息是我们从 金字塔的底部到顶部,而不是 另一种方式,所以它没有 看起来很可怕。我什么时候 必须处理父项 删除,这将是另一个不错的 头痛,但我把它留到另一个 问题;-)。
现在我的问题
您将如何以最佳方式存储数据和处理过滤?
可选:
我应该定义一个明确的递归深度限制吗? 我应该使用 SQL 还是 Java 执行过滤? SQL 肯定会更快,但在 Java 中匹配地理上下文要容易得多。
当我在 Android 平台上工作时,我有以下限制:
Java 是唯一可用的语言, 而不是整个标准库。
SQLite 是唯一可用的 DBMS。
性能和内存很重要 问题。如果你不得不选择, 电池寿命,因此 性能是重中之重。
Exotics 外部库可能无法使用 可以使用。
P.S:我深入研究了 SO,发现了一些有趣的信息(尤其是 What is the most efficient/elegant way to parse a flat table into a tree?)。这是一个提示,但不是问题解决者。
【问题讨论】:
-
澄清一下,你显示所有匹配的孩子,对吗?因此,如果您从第 2 项和第 6 项匹配查看,您将在列表中显示第 5 项和第 6 项,对吗?还是只显示第 5 项作为最匹配的子项?
-
另一个问题,地理上下文是共享的,还是有其他原因将它们放在单独的表中?
-
我只会将第 5 项显示为最接近的匹配项。地理上下文不共享,但可以单独管理,因此用户可以在地理文本目录中进行选择。
-
顺便说一句,我不应该把我自己的解决方案排除在问题之外并将其放在答案中吗?
标签: java android sqlite recursion