活动记录 postgres 检查 jsonb 数组是否包含 x 或 y

joh*_*400 2 postgresql activerecord ruby-on-rails jsonb

我有一个带有 jsonb 列的表,该列有一个嵌套的 json 数组。我想找到嵌套数组至少包含一个值的所有记录。

例如,我的模型 Person 有一个名为首选项的 jsonb 列。在 jsonb 首选项中,有几个键,其中一个值是一个数组:

Person.first.preferences = {"diet" => {"foods" => ["apples", "oranges", "bananas"]}}
Run Code Online (Sandbox Code Playgroud)

我想创建一个查询,返回其偏好 -> 饮食 -> 食物包括“苹果”或“芒果”的所有人员(例如)。

目前,我可以通过 1 个输入(即“苹果”)获得结果,如下所示:

Person.where('preferences @> ?', {'diet' => {'foods' => ['apples']}}.to_json)
Run Code Online (Sandbox Code Playgroud)

以及多个输入,如果它们都存在于数组中。因此,如果我传入 'apples' 和 'oranges',则会返回结果,因为该记录同时包含苹果和橙子。

Person.where('preferences @> ?', {'diet' => {'foods' => ['apples', 'oranges']}}.to_json)
Run Code Online (Sandbox Code Playgroud)

有没有办法传入多个变量(即 ['apples', 'mangos'])并检查嵌套的 jsonb 数组是否包含 apples 或 mangos 但​​不一定两者都包含?

以下查询没有结果,因为我的人的食物偏好不包括芒果,即使它们包括苹果。

Person.where('preferences @> ?', {'diet' => {'foods' => ['apples', 'mangos']}}.to_json)
Run Code Online (Sandbox Code Playgroud)

使用 Rails 5.2 和 Postgresql 10

谢谢!

mu *_*ort 5

首先要做的是使用->or访问数组#>,然后您可以使用?|运算符检查数组是否与您要查找的内容重叠。像这样的 SQL:

preferences->'diet'->'foods' ?| array['apples', 'mangos']
Run Code Online (Sandbox Code Playgroud)

或使用 ActiveRecord:

Person.where("preferences->'diet'->'foods' ?| array[:foods]", foods: ['apples', 'mangos'])
Run Code Online (Sandbox Code Playgroud)