【问题标题】:Match multiple keys values to database entry in TinyDB?将多个键值与 TinyDB 中的数据库条目匹配?
【发布时间】:2018-04-05 17:22:34
【问题描述】:

我很难确定是否可以使用 TinyDB 一次检查多个键值。目前我可以通过在if 语句中使用and 来检查多个字段,如下所示:

def check_table(FNAME="NULL", LNAME="NULL", MNAME="NULL"):
    if (HHK_STAFF.search(Query().FNAME == FNAME)) != [] \
    and (HHK_STAFF.search(Query().MNAME == MNAME)) != [] \
    and (HHK_STAFF.search(Query().LNAME == LNAME)) != []:
        print(HHK_STAFF.search(Query().FNAME == FNAME)[0])
    else:
        print("user does not exist")

check_table(FNAME="Some", MNAME="Random", LNAME="Person")

它可以满足我的需求,但它看起来很笨重。我希望 TinyDB 中内置了一些东西,可以执行相同的功能,而无需许多 and 语句。

我正在尝试做类似的事情:

HHK_STAFF.search(where(("FNAME", "MNAME", "LNAME")) == (FNAME, MNAME, LNAME)))

问题:

  1. 有没有人知道一种方法来查询()表以获取多个键值,而不是一次仅一个键值?

  2. 您能否列出指向此信息的链接?如果存在这些信息,我很难找到它。

这是我对 TinyDB 的简单版本:

from tinydb import TinyDB, Query


#~~~~~~~~~~~~~~~~~~~~~~< CURRENT DBPATH >~~~~~~~~~~~~~~~~~~~~~~
DB = TinyDB('./DB_PATH/HHK_DB.json')
#~~~~~~~~~~~~~~~~~~~~~~< CURRENT TABLES >~~~~~~~~~~~~~~~~~~~~~~
HHK_STAFF = DB.table("HHK_STAFF")

HHK_STAFF.insert({'EMPLOYEE_ID':'00000001', 'FNAME': 'Some', 'LNAME':'Person', 'MNAME':'Random'})


def check_table(FNAME="NULL", LNAME="NULL", MNAME="NULL"):
    if (HHK_STAFF.search(Query().FNAME == FNAME)) != [] \
    and (HHK_STAFF.search(Query().MNAME == MNAME)) != [] \
    and (HHK_STAFF.search(Query().LNAME == LNAME)) != []:
        print(HHK_STAFF.search(Query().FNAME == FNAME)[0])
    else:
        print("user does not exist")

check_table(FNAME="Some", MNAME="Random", LNAME="Person")

结果:

{'EMPLOYEE_ID': '00000001', 'FNAME': 'Some', 'LNAME': 'Person', 'MNAME': 'Random'}

【问题讨论】:

    标签: python tinydb


    【解决方案1】:

    根据Advanced Usage — TinyDB 3.8.1.post1 documentation,逻辑与将如下所示:

    q = Query()
    HHK_STAFF.search((q.FNAME == FNAME) & (q.MNAME == MNAME) & (q.LNAME == LNAME))
    

    根据git blame of tinydb/queries.py,从第一个版本开始,它就一直可用。

    【讨论】:

    • 哇,我错过了那部分。我看了那页十几次。当我有机会时,我会测试这个例子,但它似乎正是我正在寻找的。谢谢。
    • @Mike-SMT - 为了公平起见,您声称 Dan 的第二个示例并不完全符合您的要求,而它实际上与您声称的答案相同。另外,请注意,这与您自己的 check_table() 函数所做的几乎相同,但这就是您使用像 TinyDB 这样效率极低的“数据库”系统所得到的结果。
    • 感谢您指出这一点。我读它更像是我原来正在做的事情的例子。现在我再次查看它,我可以看到它与您的示例相同。我猜我今天休息了。
    • 好吧,他的答案与您自己的相似,我认为您的答案仍然是更好的答案,因为它使用单个 query() 并且文档已说明使用多个 query() 时可能会导致奇怪的问题' s
    • 我为后代修复了我的冗余 Query() 调用。我仍然会说这个值得被接受,因为 ivan 找到了实际的源代码和一个文档链接(我后来才编辑到我的)。
    【解决方案2】:

    您可以使用 python 内置 all 来实现更短、更灵活的工作,类似于您的示例代码:

    def check_table2(**query):
        if all(HHK_STAFF.search(getattr(Query(), k) == v) 
               for k, v in query.items()):
            print(HHK_STAFF.search(Query().FNAME == query['FNAME'])[0])
        else:
            print("user does not exist")
    

    但您应该确定这确实是您想要的。对应的英文是,

    "如果存在这个姓氏的人,并且有这个姓氏的人 name 存在,并且有这个中间名的人存在,不管 无论他们都是同一个人,都返回具有匹配名字的人。”

    换句话说,如果我现在将另一个人添加到您的数据库中

    HHK_STAFF.insert({'EMPLOYEE_ID':'00000002', 
                      'FNAME': 'Anne', 
                      'LNAME':'Person',
                      'MNAME':'Other'})
    

    您上面的函数将为查询返回一些内容

    check_table(FNAME="Some", MNAME="Other", LNAME="Person")
    

    即使 Some 的中间名是“Random”而不是“Other”,只是因为系统上存在中间名是“Other”的其他人

    您可能希望利用 Query 被覆盖的 __and__ operator 来查找具有您要查询的所有姓名的单个人:

    q = Query()
    HHK_STAFF.search((q.FNAME=="Anne") & 
                     (q.MNAME=="Other") & 
                     (q.LNAME=="Person"))
    

    或者,对于像我上面所做的那样使用键值的东西,使用functools.reduce

    from functools import reduce
    
    def user_matching_all(**query):
        q = Query()
        out = HHK_STAFF.search(reduce(lambda x, y: x & y,
                                      [getattr(q, k) == v
                                       for k, v in query.items()]))
        if out:
            print(out)
        else:
            print("user does not exist")
    

    【讨论】:

    • 你的第一个例子不是我想要的。无论我想交叉引用多少个字段,我都需要一个完全匹配的匹配我指定的所有字段。
    • 我想通了,所以我的答案的其余部分。
    • 刚刚意识到你的第二个例子就是我要找的。出于某种原因,我误读了该示例,使其更像我问题中的原始示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多