Home > database >  JQ — Return first element that satisfies a predicate
JQ — Return first element that satisfies a predicate

Time:03-19

I have a string like:

"The sky is blue."

and a JSON file like

[
  {
    "id": 1234,
    "name": "Entry 1",
    "keywords": [
      "orange",
      "yellow"
    ]
  }, 
  {
    "id": 2345,
    "name": "Entry 2",
    "keywords": [
      "red",
      "blue",
      "pink"
    ]
  }, 
  {
    "id": 3456,
    "name": "Entry 3",
    "keywords": [
        "green",
        "blue",
        "black"
    ]
  }
]

I want to return the first element which has a keyword that can be found in the string.

In this case I would like to have the element with the id 2345, because the keyword "blue" occurs in the string, and it is the first match.

Is there a one-line solution with JQ (e.g. with various pipes)? I'm not looking for a solution with loops.

CodePudding user response:

Using first/1 with a select expression is the right approach here

jq --arg v "The sky is blue." 'first(.[] | select(.keywords as $k | $v | match($k[])))'

produces

{
  "id": 2345,
  "name": "Entry 2",
  "keywords": [
    "red",
    "blue",
    "pink"
  ]
}

CodePudding user response:

with the above content in the input.json

query:

 jq '.[] | {id, keywords: .keywords[]} | select(.keywords == "blue") ' input.json

output:

{
  "id": 2345,
  "keywords": "blue"
}
{
  "id": 3456,
  "keywords": "blue"
}

you can get the first object from this.

CodePudding user response:

A variation based on Inian's excellent answer:

first(.[] | select(.keywords | any(inside("the sky is blue."))))

If we have the data in input.json and the string "the sky is blue." passed as a parameter we have:

jq --arg str 'the sky is blue' 'first(.[] | select(.keywords | any(inside($str))))' input.json

This returns the first element which keywords is contained within $str:

{
  "id": 2345,
  "name": "Entry 2",
  "keywords": [
    "red",
    "blue",
    "pink"
  ]
}
  • Related