How to create index on json array in postgres?












0















I have a json field called 'elements' in my table demo which contains an array 'data' containing key value pairs. the 'data' array has the below structure. the data array may have multiple json entries.I am using postgres version 9.5



{
"data": [{
"ownr": "1",
"sigUsr": [2],
"sigStat": "APPR",
"modifiedOn": 1494229698039,
"isDel": "false",
"parentId": "nil",
"disName": "exmp.json",
"uniqueId": "d88cb52",
"usrType": "owner",
"usrId": "1",
"createdOn": 1494229698039,
"obType": "file"
}]
}


In my query I have multiple filters based on obj(Eg : obj->>usrId, obj->>sigUsr etc) where obj corresponds to json_array_elements(demo.elements->'data').How do I create btree indices on filters like obj->>userId ,obj->>sigUsr? Please revert.



Regards
sur










share|improve this question





























    0















    I have a json field called 'elements' in my table demo which contains an array 'data' containing key value pairs. the 'data' array has the below structure. the data array may have multiple json entries.I am using postgres version 9.5



    {
    "data": [{
    "ownr": "1",
    "sigUsr": [2],
    "sigStat": "APPR",
    "modifiedOn": 1494229698039,
    "isDel": "false",
    "parentId": "nil",
    "disName": "exmp.json",
    "uniqueId": "d88cb52",
    "usrType": "owner",
    "usrId": "1",
    "createdOn": 1494229698039,
    "obType": "file"
    }]
    }


    In my query I have multiple filters based on obj(Eg : obj->>usrId, obj->>sigUsr etc) where obj corresponds to json_array_elements(demo.elements->'data').How do I create btree indices on filters like obj->>userId ,obj->>sigUsr? Please revert.



    Regards
    sur










    share|improve this question



























      0












      0








      0








      I have a json field called 'elements' in my table demo which contains an array 'data' containing key value pairs. the 'data' array has the below structure. the data array may have multiple json entries.I am using postgres version 9.5



      {
      "data": [{
      "ownr": "1",
      "sigUsr": [2],
      "sigStat": "APPR",
      "modifiedOn": 1494229698039,
      "isDel": "false",
      "parentId": "nil",
      "disName": "exmp.json",
      "uniqueId": "d88cb52",
      "usrType": "owner",
      "usrId": "1",
      "createdOn": 1494229698039,
      "obType": "file"
      }]
      }


      In my query I have multiple filters based on obj(Eg : obj->>usrId, obj->>sigUsr etc) where obj corresponds to json_array_elements(demo.elements->'data').How do I create btree indices on filters like obj->>userId ,obj->>sigUsr? Please revert.



      Regards
      sur










      share|improve this question
















      I have a json field called 'elements' in my table demo which contains an array 'data' containing key value pairs. the 'data' array has the below structure. the data array may have multiple json entries.I am using postgres version 9.5



      {
      "data": [{
      "ownr": "1",
      "sigUsr": [2],
      "sigStat": "APPR",
      "modifiedOn": 1494229698039,
      "isDel": "false",
      "parentId": "nil",
      "disName": "exmp.json",
      "uniqueId": "d88cb52",
      "usrType": "owner",
      "usrId": "1",
      "createdOn": 1494229698039,
      "obType": "file"
      }]
      }


      In my query I have multiple filters based on obj(Eg : obj->>usrId, obj->>sigUsr etc) where obj corresponds to json_array_elements(demo.elements->'data').How do I create btree indices on filters like obj->>userId ,obj->>sigUsr? Please revert.



      Regards
      sur







      postgresql postgresql-9.5






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 1 at 7:06









      Kaushik Nayak

      19.8k41332




      19.8k41332










      asked Jan 1 at 4:51









      sursur

      61




      61
























          1 Answer
          1






          active

          oldest

          votes


















          0














          First, if your column datatype is JSON rather than JSONB, you can only create index
          on the whole column demo.elements. Only JSONB columns can have indices on json keys.



          You might consider to change your datatype if you specify JSON in this table.



          Then, I modify your situation into a test case as follows.



          create table demo(
          elements jsonb
          );
          insert into demo values(
          '{
          "data": [
          {
          "ownr": "1",
          "sigUsr": [
          2
          ],
          "sigStat": "APPR",
          "modifiedOn": 1494229698039,
          "isDel": "false",
          "parentId": "nil",
          "disName": "exmp.json",
          "uniqueId": "d88cb52",
          "usrType": "owner",
          "usrId": "1",
          "createdOn": 1494229698039,
          "obType": "file"
          }
          ]
          }'
          );


          And query you ask can be achieved in the following ways as I can imagine.



          postgres=# -- First possible query
          postgres=# select elements->'data'->0->'usrId', elements->'data'->0->'sigUsr' from demo;
          ?column? | ?column?
          ----------+----------
          "1" | [2]
          (1 row)

          postgres=# -- Second possible query, with jsonb_array_elements()
          postgres=# select obj->>'usrId', obj->>'sigUsr' from demo d, jsonb_array_elements(d.elements->'data') as obj;
          ?column? | ?column?
          ----------+----------
          1 | [2]
          (1 row)

          postgres=#


          I can only create index with the first one, which is a restrictive use case. you need to write specific array entry in your index (in this case is the 0th element).



          postgres=# create index ON demo ((elements->'data'->0->'usrId'));
          CREATE INDEX
          postgres=#


          I can not create index for the second approach since jsonb_array_elements() returns setof jsonb type.



          postgres=# create index ON demo ((jsonb_array_elements(elements->'data')->>'usrId'));
          ERROR: set-returning functions are not allowed in index expressions
          LINE 1: create index ON demo ((jsonb_array_elements(elements->'data'...
          ^
          postgres=#


          I think you should store sub-json entries in individual rows rather than store them into a json array.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53993075%2fhow-to-create-index-on-json-array-in-postgres%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            First, if your column datatype is JSON rather than JSONB, you can only create index
            on the whole column demo.elements. Only JSONB columns can have indices on json keys.



            You might consider to change your datatype if you specify JSON in this table.



            Then, I modify your situation into a test case as follows.



            create table demo(
            elements jsonb
            );
            insert into demo values(
            '{
            "data": [
            {
            "ownr": "1",
            "sigUsr": [
            2
            ],
            "sigStat": "APPR",
            "modifiedOn": 1494229698039,
            "isDel": "false",
            "parentId": "nil",
            "disName": "exmp.json",
            "uniqueId": "d88cb52",
            "usrType": "owner",
            "usrId": "1",
            "createdOn": 1494229698039,
            "obType": "file"
            }
            ]
            }'
            );


            And query you ask can be achieved in the following ways as I can imagine.



            postgres=# -- First possible query
            postgres=# select elements->'data'->0->'usrId', elements->'data'->0->'sigUsr' from demo;
            ?column? | ?column?
            ----------+----------
            "1" | [2]
            (1 row)

            postgres=# -- Second possible query, with jsonb_array_elements()
            postgres=# select obj->>'usrId', obj->>'sigUsr' from demo d, jsonb_array_elements(d.elements->'data') as obj;
            ?column? | ?column?
            ----------+----------
            1 | [2]
            (1 row)

            postgres=#


            I can only create index with the first one, which is a restrictive use case. you need to write specific array entry in your index (in this case is the 0th element).



            postgres=# create index ON demo ((elements->'data'->0->'usrId'));
            CREATE INDEX
            postgres=#


            I can not create index for the second approach since jsonb_array_elements() returns setof jsonb type.



            postgres=# create index ON demo ((jsonb_array_elements(elements->'data')->>'usrId'));
            ERROR: set-returning functions are not allowed in index expressions
            LINE 1: create index ON demo ((jsonb_array_elements(elements->'data'...
            ^
            postgres=#


            I think you should store sub-json entries in individual rows rather than store them into a json array.






            share|improve this answer




























              0














              First, if your column datatype is JSON rather than JSONB, you can only create index
              on the whole column demo.elements. Only JSONB columns can have indices on json keys.



              You might consider to change your datatype if you specify JSON in this table.



              Then, I modify your situation into a test case as follows.



              create table demo(
              elements jsonb
              );
              insert into demo values(
              '{
              "data": [
              {
              "ownr": "1",
              "sigUsr": [
              2
              ],
              "sigStat": "APPR",
              "modifiedOn": 1494229698039,
              "isDel": "false",
              "parentId": "nil",
              "disName": "exmp.json",
              "uniqueId": "d88cb52",
              "usrType": "owner",
              "usrId": "1",
              "createdOn": 1494229698039,
              "obType": "file"
              }
              ]
              }'
              );


              And query you ask can be achieved in the following ways as I can imagine.



              postgres=# -- First possible query
              postgres=# select elements->'data'->0->'usrId', elements->'data'->0->'sigUsr' from demo;
              ?column? | ?column?
              ----------+----------
              "1" | [2]
              (1 row)

              postgres=# -- Second possible query, with jsonb_array_elements()
              postgres=# select obj->>'usrId', obj->>'sigUsr' from demo d, jsonb_array_elements(d.elements->'data') as obj;
              ?column? | ?column?
              ----------+----------
              1 | [2]
              (1 row)

              postgres=#


              I can only create index with the first one, which is a restrictive use case. you need to write specific array entry in your index (in this case is the 0th element).



              postgres=# create index ON demo ((elements->'data'->0->'usrId'));
              CREATE INDEX
              postgres=#


              I can not create index for the second approach since jsonb_array_elements() returns setof jsonb type.



              postgres=# create index ON demo ((jsonb_array_elements(elements->'data')->>'usrId'));
              ERROR: set-returning functions are not allowed in index expressions
              LINE 1: create index ON demo ((jsonb_array_elements(elements->'data'...
              ^
              postgres=#


              I think you should store sub-json entries in individual rows rather than store them into a json array.






              share|improve this answer


























                0












                0








                0







                First, if your column datatype is JSON rather than JSONB, you can only create index
                on the whole column demo.elements. Only JSONB columns can have indices on json keys.



                You might consider to change your datatype if you specify JSON in this table.



                Then, I modify your situation into a test case as follows.



                create table demo(
                elements jsonb
                );
                insert into demo values(
                '{
                "data": [
                {
                "ownr": "1",
                "sigUsr": [
                2
                ],
                "sigStat": "APPR",
                "modifiedOn": 1494229698039,
                "isDel": "false",
                "parentId": "nil",
                "disName": "exmp.json",
                "uniqueId": "d88cb52",
                "usrType": "owner",
                "usrId": "1",
                "createdOn": 1494229698039,
                "obType": "file"
                }
                ]
                }'
                );


                And query you ask can be achieved in the following ways as I can imagine.



                postgres=# -- First possible query
                postgres=# select elements->'data'->0->'usrId', elements->'data'->0->'sigUsr' from demo;
                ?column? | ?column?
                ----------+----------
                "1" | [2]
                (1 row)

                postgres=# -- Second possible query, with jsonb_array_elements()
                postgres=# select obj->>'usrId', obj->>'sigUsr' from demo d, jsonb_array_elements(d.elements->'data') as obj;
                ?column? | ?column?
                ----------+----------
                1 | [2]
                (1 row)

                postgres=#


                I can only create index with the first one, which is a restrictive use case. you need to write specific array entry in your index (in this case is the 0th element).



                postgres=# create index ON demo ((elements->'data'->0->'usrId'));
                CREATE INDEX
                postgres=#


                I can not create index for the second approach since jsonb_array_elements() returns setof jsonb type.



                postgres=# create index ON demo ((jsonb_array_elements(elements->'data')->>'usrId'));
                ERROR: set-returning functions are not allowed in index expressions
                LINE 1: create index ON demo ((jsonb_array_elements(elements->'data'...
                ^
                postgres=#


                I think you should store sub-json entries in individual rows rather than store them into a json array.






                share|improve this answer













                First, if your column datatype is JSON rather than JSONB, you can only create index
                on the whole column demo.elements. Only JSONB columns can have indices on json keys.



                You might consider to change your datatype if you specify JSON in this table.



                Then, I modify your situation into a test case as follows.



                create table demo(
                elements jsonb
                );
                insert into demo values(
                '{
                "data": [
                {
                "ownr": "1",
                "sigUsr": [
                2
                ],
                "sigStat": "APPR",
                "modifiedOn": 1494229698039,
                "isDel": "false",
                "parentId": "nil",
                "disName": "exmp.json",
                "uniqueId": "d88cb52",
                "usrType": "owner",
                "usrId": "1",
                "createdOn": 1494229698039,
                "obType": "file"
                }
                ]
                }'
                );


                And query you ask can be achieved in the following ways as I can imagine.



                postgres=# -- First possible query
                postgres=# select elements->'data'->0->'usrId', elements->'data'->0->'sigUsr' from demo;
                ?column? | ?column?
                ----------+----------
                "1" | [2]
                (1 row)

                postgres=# -- Second possible query, with jsonb_array_elements()
                postgres=# select obj->>'usrId', obj->>'sigUsr' from demo d, jsonb_array_elements(d.elements->'data') as obj;
                ?column? | ?column?
                ----------+----------
                1 | [2]
                (1 row)

                postgres=#


                I can only create index with the first one, which is a restrictive use case. you need to write specific array entry in your index (in this case is the 0th element).



                postgres=# create index ON demo ((elements->'data'->0->'usrId'));
                CREATE INDEX
                postgres=#


                I can not create index for the second approach since jsonb_array_elements() returns setof jsonb type.



                postgres=# create index ON demo ((jsonb_array_elements(elements->'data')->>'usrId'));
                ERROR: set-returning functions are not allowed in index expressions
                LINE 1: create index ON demo ((jsonb_array_elements(elements->'data'...
                ^
                postgres=#


                I think you should store sub-json entries in individual rows rather than store them into a json array.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 1 at 8:04









                C.C. HsuC.C. Hsu

                511




                511
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53993075%2fhow-to-create-index-on-json-array-in-postgres%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                    Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                    A Topological Invariant for $pi_3(U(n))$