SQL の where 句のように ディクショナリのリストから抽出するには selectattr を利用
以下のようなディクショナリのリストがあるとします。DBにおけるテーブルのデータのような構造です。
users: - name: yamada age: 42 - name: tanaka age: 26 - name: suzuki age: 32 - name: sato age: 27
ここで、「 name
が sato
であるディクショナリのリスト」を抽出したい場合は、 selectattr
を利用して以下のようにフィルター(Jinja2の機能)します。
- selectattr によるフィルタ
- debug: msg: "{{ users | selectattr('name', '==', 'sato') | list }}"
- 結果
"msg": [ { "age": 27, "name": "sato" } ]
無地に1件が抽出されました。
SQL でいうと select * from users where name='sato'
のようなイメージです。
■ 応用例: 部分一致、以上、以下など指定もできる
先ほど使用した ==
(または qeualto
、eq
)では完全一致でしたが、他にもあります。
!=
または ne
: 〜ではない
- debug: msg: "{{ users | selectattr('name', '!=', 'sato') | list }}"
"msg": [ { "age": 42, "name": "yamada" }, { "age": 26, "name": "tanaka" }, { "age": 32, "name": "suzuki" } ]
in
: 〜に含まれる
- debug: msg: "{{ users | selectattr('name', 'in', 'sssssatoooo') | list }}"
"msg": [ { "age": 27, "name": "sato" } ]
>
または gt
: 〜より大きい
- debug: msg: "{{ users | selectattr('age', '>', 27) | list }}"
"msg": [ { "age": 42, "name": "yamada" }, { "age": 32, "name": "suzuki" } ]
>=
または ge
: 〜以上
- debug: msg: "{{ users | selectattr('age', '>=', 27) | list }}"
"msg": [ { "age": 42, "name": "yamada" }, { "age": 32, "name": "suzuki" }, { "age": 27, "name": "sato" } ]
<
または lt
: 〜以下
- debug: msg: "{{ users | selectattr('age', '<', 27) | list }}"
"msg": [ { "age": 26, "name": "tanaka" } ]
<=
または le
: 〜以下
- debug: msg: "{{ users | selectattr('age', '<=', 27) | list }}"
"msg": [ { "age": 26, "name": "tanaka" }, { "age": 27, "name": "sato" } ]
■ 補足: ループと when の組み合わせとの比較
selectattr
のように抽出してから何かを処理する方法の他にも、全件ループと when
によって処理条件を指定する方法があります。
条件に合わなかった分のタスクは skipping
になります。
- Playbook: ループと when の組み合わせる場合
- debug: msg: "{{ item }}" when: - item.age <= 27 loop: "{{ users }}"
- 結果
skipping: [localhost] => (item={u'age': 42, u'name': u'yamada'}) ok: [localhost] => (item={u'age': 26, u'name': u'tanaka'}) => { "msg": { "age": 26, "name": "tanaka" } } skipping: [localhost] => (item={u'age': 32, u'name': u'suzuki'}) ok: [localhost] => (item={u'age': 27, u'name': u'sato'}) => { "msg": { "age": 27, "name": "sato" } }
先に selectattr
でフィルタしたほうがログがスッキリして、処理速度も早いかもしれません。
Playbook としてのシンプルさという点は、ループと when の組み合わせのほうがよさそうです。
参考: エラーが発生する場合
TemplateRuntimeError: no test named 'equalto'
のようなエラーが発生し場合は、 Jinja2 のバージョンを確認してください。利用のバージョンで、指定した評価式が対応していないことがあります。