gpt4 book ai didi

python - 使用 Pyparsing 生成 Sql 到 Pymongo

转载 作者:可可西里 更新时间:2023-11-01 09:13:47 24 4
gpt4 key购买 nike

我正在使用目前世界上“最棒”的解析库。解析。手头的问题是从给定的 SQL 字符串(对于选择语句)生成 PyMongo 字典。我使用的语法定义如下:

sql_stmt = (select_key_word + ('*' | column_list).setResultsName
("columns") + form_key_word + table_name_list.setResultsName
("collections") +
Optional(where_condition, "").setResultsName("where"))

这里的 select_key_word、column_list 等结构是有效的语法定义。并使用它我可以解析一个字符串,如“Select * from collection_1 where (Sal = 1000 or Sal=5000) AND Car>2”我遇到的问题是,正在解析的部分是这样的:

[[u'where', [u'(', [u'Sal', '=', u'1000'], 'or', [u'Sal', '=', u'5000'], u')'], 'and', [u'Car', '>', u'2']]] 

如果我想将它翻译成 sqlish 的东西,那很好。但是在 pymongo 中的有效表示是这样的:

{u'$or': [{u'$and': [{u'Sal': u'1000'}, {u'Sal': u'5000'}]}, {u'Car': {u'$gte': u'2'}}]}

这就是我被困的地方。谁能给我一个方向?在我看来,setParseAction 将是一种可行的方法,但就是想不通

where_contidion 的代码是:

where_expr = Forward()
and_keyword = get_conjunction_as_grammar("and")
or_keyword = get_conjunction_as_grammar("or")
in_operation = get_operation_as_grammar("in")

column_value = get_real_number_as_grammar() | get_int_as_grammar() | \
quotedString
binary_operator = get_bin_op_as_grammar()
col_name = get_column_name_as_grammar()

where_condn = Group(
(col_name + binary_operator + column_value) |
(col_name + in_operation + "(" + delimitedList(column_value) + ")" ) |
("(" + where_expr + ")")
)
where_expr << where_condn + ZeroOrMore((and_keyword | or_keyword)
+ where_expr)

where_condition = Group(CaselessLiteral("where") + where_expr)

提前致谢。如果您需要任何其他信息,请告诉我。

最佳答案

是的,解析 Action 正是这类项目的用武之地。此外,如果您尝试计算一个表达式,该表达式可以用括号嵌套不同优先级的操作,那么 operatorPrecedence 通常是一个方便的快捷方式:

from pyparsing import *

and_keyword = CaselessKeyword("and")
or_keyword = CaselessKeyword("or")
in_operation = CaselessKeyword("in")

value = quotedString | Word(alphanums)
comparisonOp = oneOf("= != > < >= <=")
LPAR,RPAR = map(Suppress,"()")
valueList = LPAR + delimitedList(value) + RPAR
comparisonExpr = value + comparisonOp + value | value + in_operation + Group(valueList)
def makePymongoComparison(tokens):
v1,op,v2 = tokens
if op != 'in':
if op != '=':
op = {
"!=" : "$ne",
">" : "$gt",
"<" : "$lt",
">=" : "$gte",
"<=" : "$lte",
}[op]
v2 = "{'%s': '%s'}" % (op, v2)
return "{'%s': '%s'}" % (v1, v2)
else:
return "{'%s': {'$in': [%s]}}" % (v1, ','.join("'%s'"%v for v in v2))
comparisonExpr.setParseAction(makePymongoComparison)

def handleBinaryOp(op):
def pa(tokens):
return "{'$%s': %s}" % (op, ', '.join(tokens.asList()[0][::2]))
return pa
handleAnd = handleBinaryOp("and")
handleOr = handleBinaryOp("or")
whereOperand = comparisonExpr
where_expr = operatorPrecedence(whereOperand,
[
(and_keyword, 2, opAssoc.LEFT, handleAnd),
(or_keyword, 2, opAssoc.LEFT, handleOr),
])

where_condition = Group(CaselessLiteral("where") + where_expr)

print where_expr.parseString("(Sal = 1000 or Sal=5000) AND Car>2")[0]
print where_expr.parseString("(Sal = 1000 or Sal=5000) AND Car in (1,2,3)")[0]

打印:

{'$and': {'$or': {'Sal': '1000'}, {'Sal': '5000'}}, {'Car': '{'$gt': '2'}'}}
{'$and': {'$or': {'Sal': '1000'}, {'Sal': '5000'}}, {'Car': {'$in': ['1','2','3']}}}

仍然需要一些调整,但我希望这能让你走得更远。

关于python - 使用 Pyparsing 生成 Sql 到 Pymongo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13190090/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com