为什么这个sqlalchemy or_表达式不能使用true子句?

时间:2016-03-30 20:25:14

标签: python sqlalchemy

我有一个sqlalchemy声明模型,看起来像:

expr = or_(Post.owner == current_user,  # current_user is ORM User1
           Post.public == True,
           Post.shared.contains(another_user))

posts = session.query(Post).filter(expr).all()

在我的测试数据库中,我有一个帖子Post1的用户User1。 Post1没有任何与之关联的共享用户。我尝试了一个查询:

posts

但是session.query(Post).filter(Post.owner == current_user).all() # returns Post1 session.query(Post).filter(Post.public == True).all() # returns Post1 session.query(Post).filter(Post.shared.contains(another_user)).all() # empty list as expected 是一个空列表。以下是各个查询:

or_

如果确认三个单独查询中有两个有效,原始Post.shared.contains(another_user)的工作原理是什么?

编辑#1:

Post.shared.any(User.id == another_user_id)替换or_可修复<?php $custom_fields = get_option( 'wp_estate_custom_fields', true); if(isset($custom_fields[0])){ for($i = 0; $i < count($custom_fields); ++$i) { if($custom_fields[$i][0] != 'MYNAMEHERE') continue; $name = $custom_fields[$i][0]; $label = $custom_fields[$i][1]; $type = $custom_fields[$i][2]; $order = $custom_fields[$i][3]; $dropdown_values = $custom_fields[$i][4]; $slug = str_replace(' ','_',$name); $slug = wpestate_limit45(sanitize_title( $name )); $slug = sanitize_key($slug); $post_id = $post->ID; $show = 1; if (function_exists('icl_translate') ){ $label = icl_translate('wpestate','wp_estate_property_custom_front_'.$label, $label ) ; } if($i%2!=0){ print '<p class="half_form half_form_last">'; }else{ print '<p class="half_form">'; } $value=$custom_fields_array[$slug]; wpestate_show_custom_field($show,$slug,$name,$label,$type,$order,$dropdown_values,$post_id,$value); break; } } ?> 查询问题。但是现在我想知道为什么一个有效,另一个没有。

1 个答案:

答案 0 :(得分:1)

您没有包含辅助表定义,但我认为它是这样的:

shared_post = Table(
    'shared_post', Base.metadata,
    Column('user_id', Integer,
           ForeignKey('user.id', ondelete='cascade'), nullable=False),
    Column('post_id', Integer,
           ForeignKey('post.id', ondelete='cascade'), nullable=False)
)

调试SQLAlchemy查询的一个良好开端是尝试打印部分表达式甚至完整查询:

print(expr)  # where expr is the original or_(...)

产量

:param_1 = post.owner_id OR post.public = 1 OR post.id = shared_post_1.post_id AND :param_2 = shared_post_1.user_id

我们看到.contains()方法产生了一个隐式连接和一个没有括号的2个表达式的AND:连接谓词

post.id = shared_post_1.post_id

,第二个表达式是给定用户的实际检查

:param_2 = shared_post_1.user_id

因此,您的谓词现在由OR组成,后跟一个永远不会满足的AND。

完整查询

SELECT post.id AS post_id, post.owner_id AS post_owner_id, post.name AS post_name, post.public AS post_public 
FROM post, shared_post AS shared_post_1 
WHERE ? = post.owner_id OR post.public = 1 OR post.id = shared_post_1.post_id AND ? = shared_post_1.user_id