Sqlalchemy:使用两个ARRAY类型列进行过滤操作

时间:2017-04-23 15:26:09

标签: python arrays sqlalchemy

我有两个课:问题和用户。 Question类有一个名为category_ids的{​​{1}}类型的字段,而User类有一个对象Column(ARRAY(Integer)),它有一个名为preferences的字段,类型为{{ 1}}。

我正在尝试从用户首选项中查询ignored_categories字段中显示的Column(ARRAY(Integer))字段中至少没有一个值的所有问题,或者如果前一个为真,那么category_ids字段中不在用户首选项字段ignored_categories中的其他值。因此,以下情况应该如此:

  • category_ids = []和ignore_categories = [1,2,3] =>应该通过。
  • category_ids = [1,2,4]和ignored_categories = [1,2,3] =>应该通过。
  • category_ids = [1]和ignored_categories = [1,2,3] =>应该忽略。
  • category_ids = [1,2,3]和ignored_categories = [1,2,3] =>应该忽略。
  • category_ids = [1,2,3,4]和ignored_categories = [1,2,3] =>应该通过。
  • category_ids = [5,7]和ignored_categories = [1,2,3] =>应该通过。

这是我到目前为止所提出的:

category_ids

问题是ignored_categories仅测试user = DBSession.query(User).filter_by(id=user_id).one() # this gets the user object query = DBSession.query(Question).order_by(Question.created_at.desc()) query = query.filter( or_( not_( Question.category_ids.overlap(user.preferences.ignored_categories) ), Question.category_ids.contains(user.preferences.ignored_categories) ) ) contains的超集,这无法为数据集提供正确的结果,例如:

  • category_ids = [1]和ignored_categories = [1,2,3] =>应该忽略。

因此,它需要另一个条件来测试是否存在至少一个匹配的值,而没有其他值不匹配。

category_ids函数仅测试两个数组中是否存在至少一个值,但是这样的测试失败,例如:

  • ignored_categories = [1,2,4]和overlap = [1,2,3] =>应该通过。

哪个应该通过,但它没有,因为我需要否定操作。如果我不否定它,它只会过滤掉绝对没有共同点的数组。

编辑:这是我的表格的样子:

category_ids

1 个答案:

答案 0 :(得分:0)

这个问题相当于category_ids中找不到ignored_categories中不存在的元素,特殊情况是如果category_ids为空,则不会被忽略。

这可以通过连接表完成,如下所示:

SELECT DISTINCT questions.*
FROM questions
LEFT JOIN question_categories ON questions.id = question_categories.question_id
WHERE (
  question_categories.category_id IS NULL  -- special case where question has no categories
  OR question_categories.category_id NOT IN (
    SELECT category_id FROM user_ignored_categories WHERE user_id = 123  -- for this user
  )  -- find a category that isn't ignored
)

要使用数组执行此操作,您可以执行以下操作:

SELECT questions.*
FROM questions
WHERE (
  cardinality(categories) = 0  -- special case where question has no categories
  OR NOT ((SELECT ignored_categories FROM users WHERE id = 123) @> categories)
);

您可以针对您的数据here测试这些内容。