Hi! Let's consider some examples.
# select '[1,2]'::jsonb @> '[1,2,2]'::jsonb; ?column? ---------- f (1 row) One may think it's because second jsonb array contain two "2". So, contains takes care about count of equal elements. # select '[1,1,2]'::jsonb @> '[1,2,2]'::jsonb; ?column? ---------- t (1 row) But, it's not. Jsonb contains takes care only about length of array. # select '[[1,2]]'::jsonb @> '[[1,2,2]]'::jsonb; ?column? ---------- t (1 row) Even more weird :) The reason why jsonb contains behaves so is check in the beginning of jsonb_contains. It makes fast check of jsonb type and elements count before calling JsonbDeepContains. if (JB_ROOT_COUNT(val) < JB_ROOT_COUNT(tmpl) || JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl)) PG_RETURN_BOOL(false); It's likely that "JB_ROOT_COUNT(val) < JB_ROOT_COUNT(tmpl)" should be checked only for objects, not arrays. Also, should JsonbDeepContains does same fast check when it deals with nested objects? ------ With best regards, Alexander Korotkov.