adriank / ObjectPath

The agile query language for semi-structured data
http://objectpath.org
MIT License
380 stars 93 forks source link

Query string for nested array #60

Closed ghost closed 2 years ago

ghost commented 6 years ago

I want to find the element of the array where firstName is John and has a phoneNumber of type iPhone.

[{
  "firstName": "John",
  "age"      : 26,
  "phoneNumbers": [
    {
      "type"  : "iPhone",
      "number": "0123-4567-8888"
    },
    {
      "type"  : "home",
      "number": "0123-4567-8910"
    }
  ]
},
{
  "firstName": "Johny",
  "lastName" : "doe",
  "age"      : 26,
  "address"  : {
    "streetAddress": "naist street",
    "city"         : "Nara",
    "postalCode"   : "630-0192"
  },
  "phoneNumbers": [
    {
      "type"  : "iPhone",
      "number": "0123-4567-8888"
    },
    {
      "type"  : "home",
      "number": "0123-4567-8910"
    }
  ]
}] 

However I received a syntax error. Here is the session:

Loading JSON document from simple.json... done. $..[@.firstName is 'John'] [{ "age": 26, "phoneNumbers": [ { "type": "iPhone", "number": "0123-4567-8888" }, { "type": "home", "number": "0123-4567-8910" } ], "firstName": "John" }] $..[@.firstName is 'John' and @.phoneNumbers[].type is 'iPhone'] Syntax error ('').

What I am doing wrong?

Thanks in advance.

adriank commented 6 years ago

$.*[@.firstName is 'John' and @.phoneNumbers.phone is 'iPhone']

  1. You don't need to use .. operator. It's slow because it deep searches the whole tree.
  2. You must use . This means that you want to take all elements. $.name returns a list of all names, $. returns the whole list.
  3. phoneNumbers*[*].type - bolded chars is some nasty typo.

Greetings, Adrian Kalbarczyk

http://kalbarczyk.co

On Thu, Jan 11, 2018 at 10:54 PM, std::lef notifications@github.com wrote:

I wan to find the element of the array where firstName is John and has a phoneNumber of type iPhone.

[{ "firstName": "John", "age" : 26, "phoneNumbers": [ { "type" : "iPhone", "number": "0123-4567-8888" }, { "type" : "home", "number": "0123-4567-8910" } ] }, { "firstName": "Johny", "lastName" : "doe", "age" : 26, "address" : { "streetAddress": "naist street", "city" : "Nara", "postalCode" : "630-0192" }, "phoneNumbers": [ { "type" : "iPhone", "number": "0123-4567-8888" }, { "type" : "home", "number": "0123-4567-8910" } ] }]

However I received a syntax error. Here is the session:

Loading JSON document from simple.json... done.

$..

[@.firstName is 'John'] [{ "age": 26, "phoneNumbers": [ { "type": "iPhone", "number": "0123-4567-8888" }, { "type": "home", "number": "0123-4567-8910" } ], "firstName": "John" }] $..[@.firstName is 'John' and @.phoneNumbers[ ].type is 'iPhone'] Syntax error ('').

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/adriank/ObjectPath/issues/60, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKycsC7Xo8xJtmPnqWqqD-edL8DJ7Nbks5tJoMzgaJpZM4RbgbP .

ghost commented 6 years ago

$.*[@.firstName is 'John' and @.phoneNumbers.type is 'iPhone'] still returns an empty [].

ObjectPath interactive shell
ctrl+c to exit, documentation at http://adriank.github.io/ObjectPath.

Loading JSON document from simple.json... done.
>>> $.*[@.firstName is 'John' and @.phoneNumbers.type is 'iPhone'] 
[]
$ objectpath -d  -e "$.*[@.firstName is 'John' and @.phoneNumbers.type is 'iPhone']" simple.json 
INFO@35 All strings will be cut to 100 chatacters.
START@43 Tree.execute
PARSE STAGE
('[', ('.', ('(root)', 'rs'), ('*',)), ('and', ('is', ('.', ('(current)',), ('name', 'firstName')), 'John'), ('is', ('.', ('.', ('(current)',), ('name', 'phoneNumbers')), ('name', 'type')), 'iPhone')))
START@56 executing node '('[', ('.', ('(root)', 'rs'), ('*',)), ('and', ('is', ('.', ('(current)',), ('name', 'firstName')), ...'
START@56 executing node '('.', ('(root)', 'rs'), ('*',))'
START@56 executing node '('(root)', 'rs')'
DEBUG@260 . left is '[{u'age': 26, u'phoneNumbers': [{u'type': u'iPhone', u'number': u'0123-4567-8888'}, {u'type': u'home...'
END@263 . returning '[{u'age': 26, u'phoneNumbers': [{u'type': u'iPhone', u'number': u'0123-4567-8888'}, {u'type': u'home...'
DEBUG@319 found '('and', ('is', ('.', ('(current)',), ('name', 'firstName')), 'John'), ('is', ('.', ('.', ('(curr...' selector. executing on [{u'age': 26, u'phoneNumbers': [{u'type': u'iPhone', u'number': u'0123-4567-8888'}, {u'type': u'...
DEBUG@337 found and operator in selector
UnboundLocalError: local variable 'nodeList' referenced before assignment
ghost commented 6 years ago

This one worked:

>>> $.*[@.firstName is 'John' and 'iPhone' in @.phoneNumbers.type]
[{
  "age": 26,
  "firstName": "John",
  "phoneNumbers": [
    {
      "type": "iPhone",
      "number": "0123-4567-8888"
    },
    {
      "type": "home",
      "number": "0123-4567-8910"
    }
  ]
}]
>>> 
adriank commented 6 years ago

This is more than strange. Some regression happened. ᐧ

Greetings, Adrian Kalbarczyk

http://kalbarczyk.co

On Fri, Jan 12, 2018 at 12:01 AM, std::lef notifications@github.com wrote:

This one worked:

$.*[@.firstName is 'John' and 'iPhone' in @.phoneNumbers.type] [{ "age": 26, "firstName": "John", "phoneNumbers": [ { "type": "iPhone", "number": "0123-4567-8888" }, { "type": "home", "number": "0123-4567-8910" } ] }]

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adriank/ObjectPath/issues/60#issuecomment-357090005, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKycjrbHh3miV1w5Qc0ZnfeoBgHLXT3ks5tJpLZgaJpZM4RbgbP .

ghost commented 6 years ago

So do you think is a bug?

>>> $..phoneNumbers.type
[
  "iPhone",
  "home",
  "iPhone",
  "home"
]
adriank commented 6 years ago

yes, I'll try to fix it now. ᐧ

Greetings, Adrian Kalbarczyk

http://kalbarczyk.co

On Fri, Jan 12, 2018 at 12:14 AM, std::lef notifications@github.com wrote:

So do you think is a bug?

$..phoneNumbers.type [ "iPhone", "home", "iPhone", "home" ]

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adriank/ObjectPath/issues/60#issuecomment-357092718, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKycm8V91S6tXBlfjTZrxGJg6EqSEQKks5tJpXlgaJpZM4RbgbP .

adriank commented 6 years ago

Even not a bug, this puts the whole point of OP into a coffin. ᐧ

Greetings, Adrian Kalbarczyk

http://kalbarczyk.co

On Fri, Jan 12, 2018 at 12:15 AM, Adrian Kalbarczyk < adrian.kalbarczyk@gmail.com> wrote:

yes, I'll try to fix it now. ᐧ

Greetings, Adrian Kalbarczyk

http://kalbarczyk.co

On Fri, Jan 12, 2018 at 12:14 AM, std::lef notifications@github.com wrote:

So do you think is a bug?

$..phoneNumbers.type [ "iPhone", "home", "iPhone", "home" ]

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adriank/ObjectPath/issues/60#issuecomment-357092718, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKycm8V91S6tXBlfjTZrxGJg6EqSEQKks5tJpXlgaJpZM4RbgbP .

ghost commented 6 years ago

Thanks Adrian, pls ping when the fix is merged.

Lef

ghost commented 6 years ago

Something that might help you debugging:

When I use the in operator after the @.firstName is John the query returns. However if the query is *$.['iPhone' in @.phoneNumbers.type]** nothing is returned back.

>>> $.*[@.firstName is 'John' and 'iPhone' in @.phoneNumbers.type]
[{
  "age": 26,
  "phoneNumbers": [
    {
      "type": "iPhone",
      "number": "0123-4567-8888"
    },
    {
      "type": "home",
      "number": "0123-4567-8910"
    }
  ],
  "firstName": "John"
}]
>>> 'iPhone' in @.phoneNumbers.type
true
>>> $.*[@.firstName is 'John' and 'iPhone' in @.phoneNumbers.type]
[{
  "age": 26,
  "phoneNumbers": [
    {
      "type": "iPhone",
      "number": "0123-4567-8888"
    },
    {
      "type": "home",
      "number": "0123-4567-8910"
    }
  ],
  "firstName": "John"
}]
>>> $.*['iPhone' in @.phoneNumbers.type]
[]
adriank commented 6 years ago

OK, it's not something for one evening. The bug that I was referring to doesn't occur in OP available through github. @.a.b where a is a list doesn't work because it was never implemented. It's unlikely that I will find time for it in the near future.

Greetings, Adrian Kalbarczyk

http://kalbarczyk.co

On Fri, Jan 12, 2018 at 12:06 PM, std::lef notifications@github.com wrote:

Something that might help you debugging:

When I use the in operator after the @.firstName is John the query returns. However if the query is $.['iPhone' in @.phoneNumbers.type]* nothing is returned back.

$.[@.firstName is 'John' and 'iPhone' in @.phoneNumbers.type] [{ "age": 26, "phoneNumbers": [ { "type": "iPhone", "number": "0123-4567-8888" }, { "type": "home", "number": "0123-4567-8910" } ], "firstName": "John" }] 'iPhone' in @.phoneNumbers.type true $.[@.firstName is 'John' and 'iPhone' in @.phoneNumbers.type] [{ "age": 26, "phoneNumbers": [ { "type": "iPhone", "number": "0123-4567-8888" }, { "type": "home", "number": "0123-4567-8910" } ], "firstName": "John" }] $.*['iPhone' in @.phoneNumbers.type] []

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/adriank/ObjectPath/issues/60#issuecomment-357210438, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKych5c1MCg-2L2Kwk1_4LsTYEdB-5qks5tJzyvgaJpZM4RbgbP .

adriank commented 5 years ago

Note to myself:

@.phoneNumbers.type in *$.['iPhone' in @.phoneNumbers.type] always return an array even if there is only one type. This needs further investigation, but maybe I should add a for loop in the is operator when there is ITERABLE on any of side of the is** operator

daxamin commented 4 years ago

@adriank Any updates on this? I am trying to do something similar in Python3 and haven't had any success yet.

{
  makes: [
      {
    name: toyota,
    cars: [
       {
          name: carmy,
          star: 5
       },
       {
          name: prius,
          star: 4
       }
    },
   {
      ...another object for make...
   }
 ]
}

Ideally I would want a query to return Boolean if there is any car named camry. I've tried the following - tree.execute("$.makes['camry' in @.cars.name]") tree.execute("$.makes[@.cars]['camry' in @.name]")

Greatly appreciate any help here. Thanks

adriank commented 4 years ago

$.makes.cars['camry' in @.name http://cars.name/]

If it doesn't work in OP, check if Sakstig https://pypi.org/project/sakstig/ handles your case.

Greetings, Adrian Kalbarczyk

https://kalbarczyk.co | https://devyard.io

On Wed, Jan 8, 2020 at 10:22 PM Dax Amin notifications@github.com wrote:

@adriank https://github.com/adriank Any updates on this? I am trying to do something similar in Python3 and haven't had any success yet.

{ makes: [ { name: toyota, cars: [ { name: carmy, star: 5 }, { name: prius, star: 4 } }, { ...another object for make... } ] }

Ideally I would want a query to return Boolean if there is any car named camry. I've tried the following - tree.execute("$.makes['camry' in @.cars.name]") tree.execute("$.makes[@.cars]['camry' in @.name]")

Greatly appreciate any help here. Thanks

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/adriank/ObjectPath/issues/60?email_source=notifications&email_token=AABLE4U3P3SZDK6LU2O6J6TQ4Y7XZA5CNFSM4ELOA3H2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIOAQ5I#issuecomment-572262517, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABLE4XNHP6VA2YTLZEEXB3Q4Y7XZANCNFSM4ELOA3HQ .

daxamin commented 4 years ago

Thank you @adriank. Sakstig handled my use-case very well.