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 のバージョンを確認してください。利用のバージョンで、指定した評価式が対応していないことがあります。