mongodb 中的递归查找子目录 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
among
0.01D
V2EX    MongoDB

mongodb 中的递归查找子目录

  •  1
     
  •   among 2021-12-01 16:44:01 +08:00 2634 次点击
    这是一个创建于 1409 天前的主题,其中的信息可能已经有所发展或是发生改变。

    # 目录表 class TC_struct(Document): name = StringField() #目录名 parent = ObjectIdField() #上层目录的 id # 文件表 class TC_item(Document): # 所在目录 parent = ReferenceField(TC_struct) #所在的目录 

    根据目录,递归查找目录中的所有文件。

    #先找到所有的目录。path_id 为所选择目录的 id path_ls = recurs_path(TC_struct, path_id)

    #然后找到目录下的所有文件 qry_list = Q(parent__in=path_ls)

    #递归查找目录的方法。

    def recurs_path(tb_cls, path_id): rds = tb_cls.objects(parent=ObjectId(path_id)).only('id') rt = list() rt.append(ObjectId(path_id)) for rd in rds: # 递归查找子目录中的子目录 rt.extend(recurs_path(tb_cls, rd._id)) return rt 

    现在的问题是,如果目录结构很深,如有 4000 多个目录,在递归的时候,耗时特别长。

    有没有方法,可以提升递归时的效率。 根本的需求是:递归查找目录中的所有文件。

    11 条回复    2021-12-01 18:24:37 +08:00
    among
        1
    among  
    OP
       2021-12-01 16:48:59 +08:00
    4000 多个字目录,响应时间能有 4s 多。
    ipwx
        2
    ipwx  
       2021-12-01 16:59:21 +08:00
    就算是操作系统上面递归子目录也这么慢啊。。。

    你要检索的时候秒出结果,你就需要加索引:

    1. 要么把所有目录的前缀抽出来当 tag 扔进倒排索引。
    2. 要么找个支持前缀匹配的数据库。

    说实话你可以自己写一个程序挂在那里跑,专门维护内存索引,绝对不慢
    among
        3
    among  
    OP
       2021-12-01 17:27:54 +08:00
    mongodb 中的 aggregate 能否支持这种。
    libook
        4
    libook  
       2021-12-01 17:45:12 +08:00
    你可以先查叶子目录名,看有几个符合要求的,然后再想根递归查询,中间不符合要求的过滤掉,越靠近根目录,候选就越少,最终剩下一个到根目录的候选就是你要的结果,或者到根之前 0 候选就表明目录不存在。然后拿着叶子目录的 ID 去文件表里查,可以一次性查到。

    不知道你的场景这样是不是会有效。
    rushpu
        5
    rushpu  
       2021-12-01 17:49:47 +08:00   1
    among
        6
    among  
    OP
       2021-12-01 17:51:37 +08:00
    @libook

    现在的算法就是根据跟的 id ,查找他目录下面的字目录,然后在递归查找这个子目录中子目录,一层层递归。
    最后得到所有的目录的 id 的 list , 最后根据这个 list ,找到目录在这些 list 中的文件。

    请过时间分析,时间都花在递归目录上了,查找文件很快。
    fgwmlhdkkkw
        7
    fgwmlhdkkkw  
       2021-12-01 17:53:06 +08:00
    做所有文件名和所有_id 的索引……
    fgwmlhdkkkw
        8
    fgwmlhdkkkw  
       2021-12-01 17:54:03 +08:00
    或者说,存的时候就倒着存。
    libook
        9
    libook  
       2021-12-01 17:59:06 +08:00
    @among #6 要不然就是空间换时间,你把所有目录的完整路径存到一个
    libook
        10
    libook  
       2021-12-01 17:59:43 +08:00
    @among #6 要不然就是空间换时间,你把所有目录的完整路径存到一个单独的表里,用字符串一次性匹配。
    zzl22100048
        11
    zzl22100048  
       2021-12-01 18:24:37 +08:00
    改成对象存储的那种模式,前缀匹配
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     887 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 20:55 PVG 04:55 LAX 13:55 JFK 16:55
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86