Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cBZ4W-0004oS-MI for pgsql-hackers@arkaria.postgresql.org; Tue, 29 Nov 2016 03:27:08 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1cBZ4V-00020g-Nv for pgsql-hackers@arkaria.postgresql.org; Tue, 29 Nov 2016 03:27:07 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1cBZ35-0008SX-RD for pgsql-hackers@postgresql.org; Tue, 29 Nov 2016 03:25:40 +0000 Received: from sub4.mail.dreamhost.com ([69.163.253.135] helo=homiemail-a90.g.dreamhost.com) by magus.postgresql.org with esmtps (TLS1.1:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84_2) (envelope-from ) id 1cBZ33-0000sN-3m for pgsql-hackers@postgresql.org; Tue, 29 Nov 2016 03:25:39 +0000 Received: from homiemail-a90.g.dreamhost.com (localhost [127.0.0.1]) by homiemail-a90.g.dreamhost.com (Postfix) with ESMTP id 8D923A005A13; Mon, 28 Nov 2016 19:25:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=cryptonector.com; h=date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=cryptonector.com; bh=1MfqbJUruRm6Er V9Lt8Depxz5So=; b=pNsnsO5+OH9pLlv2wCy5w5cZiQxwZmsz8mUlMvtVNkcCqN X5DTZgzFhMe3lfXfMc/c9KP2fEf0oU2QYwg915O92Km3H23GI4IFn8w7OFA6FjAF tHfQl7VkcVHLzSDAlAb6VDLyo3FKNF4F+70kk/aGVVs+arfsFWJ5Dbd5EGqpI= Received: from localhost (cpe-70-123-158-140.austin.res.rr.com [70.123.158.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: nico@cryptonector.com) by homiemail-a90.g.dreamhost.com (Postfix) with ESMTPSA id ED5F0A005A12; Mon, 28 Nov 2016 19:25:30 -0800 (PST) Date: Mon, 28 Nov 2016 21:25:29 -0600 From: Nico Williams To: "David G. Johnston" Cc: Christian Convey , Pavel Stehule , David Fetter , PostgreSQL Hackers , Tom Lane Subject: Re: Tackling JsonPath support Message-ID: <20161129032526.GD24797@localhost> References: <20681.1479057226@sss.pgh.pa.us> <20161128162639.GB27143@fetter.org> <20161128192343.GD11117@localhost> <20161129022623.GB24797@localhost> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) X-Pg-Spam-Score: -1.5 (-) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org On Mon, Nov 28, 2016 at 08:00:46PM -0700, David G. Johnston wrote: > IMO jq is considerably closer to XSLT than XPath - which leads me to figure > that since xml has both that JSON can benefit from jq and json-path. I'm > not inclined to dig too deep here but I'd rather take jq in the form of > "pl/jq" and have json-path (abstractly) as something that you can use like > "pg_catalog.get_value(json, json-path)" JSONPath looks a lot like a small subset of jq. Here are some examples: JSONPath | jq ------------------------------------------------------------------- $.store.book[0].title | .store.book[0].title $['store']['book'][0]['title'] | .["store"]["book"][0]["title"] $..author | ..|.author $.store.* | .store[] $.store..price | .store|..|.price? $..book[2] | [..|.book?][2] $..book[?(@.isbn)] | ..|.book?|select(.isbn) $..book[?(@.price<10)] | ..|.book?|select(.price<10) $..* | ..? Of course, jq can do much more than this. E.g., # Output [, <price>] of all books with an ISBN: ..|.book?|select(.isbn)|[.title,.price] # Output the average price of books with ISBNs appearing anywhere in # the input document: reduce (..|.book?|select(.isbn)|.price) as $price ( # Initial reduction state: {price:0,num:0}; # State update .price = (.price * .num + $price) / (.num + 1) | .num += 1) | # Extract average price .price Of course one could just wrap that with a function: def avg(pathexp; cond; v): reduce (pathexp | select(cond) | v) as $v ({v: 0, c: 0}; .v = (.v * .c + $v) / (.c + 1) | .c += 1) | v; # Average price of books with ISBNs: avg(..|.book?; .isbn; .price) # Average price of all books: avg(..|.book?; true; .price) There's much, much more. Note that jq comes with a C implementation. It should be easy to make bindings to it from other programming language run-times. Nico -- -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers