16

Given then following JSON

[
  {
    "id": "1",
    "name": "sausage",
    "value": 100
  },
  {
    "id": "2",
    "name": "spam",
    "value": 200
  },
  {
    "id": "3",
    "name": "eggs",
    "value": 300
  }
]

I can select a single record with id=3 with:

jq '.[] | select(.id=="3") | .name,.value' data.json
### > "sausage"
### > "100"

But how to select several id's, i.e. the items with id in (1,2)?

## this is something I wish I could do
jq '.[] | select(.id in ("1", "2") | .name,.value' data.json 

I tried:

jq '.[] | select(.id=="1") or select(.id=="2") | .name,.value' data.json

but this results in an error.

ccpizza
  • 28,968
  • 18
  • 162
  • 169
  • @JeffMercado, I wander why does `jq 'map(select(.id | in(["1","3"])))' data.json` not working? How do you think? – RomanPerekhrest Oct 02 '17 at 18:45
  • `in` is confusing. The docs say [`key | in(object)` is the inverse of `object | has(key)`](https://stedolan.github.io/jq/manual/#in) so to use `in` here you would want something like `map( select( .id | in({"1":true, "3":true})))`. If you want to search within an array `["1","3"]` then [inside](https://stedolan.github.io/jq/manual/#inside) may be what you want here as long as you use `[.id]` instead of `.id` e.g. `map( select([.id] | inside(["1","3"])) )` – jq170727 Oct 02 '17 at 21:45

1 Answers1

32

Try this:

.[] | select(.id == "3" or .id == "2") | .name,.value

Demo

bhansa
  • 7,282
  • 3
  • 30
  • 55
  • 1
    and thanks for the jqplay.org! so handy! – ccpizza Oct 02 '17 at 17:14
  • 3
    As suggested in the other similar [answer](https://stackoverflow.com/a/38126806/191246) to a similar question it can be further reduced to `.[] | select(.id == ("3", "2")) | .name,.value`. – ccpizza Oct 02 '17 at 20:57
  • One thing to beware of when using `.id == ("3","2")` is that it will do more comparisons then `.id == "3" or .id == "2"` would. You can see this by adding a `debug` e.g. try `.[] | select(.id == "3" or .id == "2" | debug) | .name,.value` and `.[] | select(.id == ("3", "2") | debug) | .name,.value` – jq170727 Oct 02 '17 at 21:55
  • 3
    To overcome the issue raised by @jq170727, simply wrap the call to `select` in a call to `first` (available in jq 1.4 and later), e.g. `first(select(.id == ("3","2")))` – peak Oct 02 '17 at 22:47
  • Perhaps it's my version of jq (1.5 osx/homebrew) but I do not observe fewer invocations of debug with `.[] | first(select(.id == ("3","2") | debug)) | .name, .value` compared to `.[] | select(.id == ("3","2") | debug) | .name, .value`. I also observe 6 (2 tests * 3 rows) invocations on https://jqplay.org/s/9wQ-m15wjr – jq170727 Oct 02 '17 at 23:25
  • If I include `def first(g): label $out | g | ., break $out; ` from master I observe 5 invocations instead of 6 as expected. – jq170727 Oct 02 '17 at 23:30