MongoDB Match an array with $type?










7














I have a MongoDb collection contains of 284.116 tweets. The problem is the "author" field in some objects are in object type, but in other objects -this "author" field- are in array type. So the problem is I want to filter which ones are Array, and which ones are Object.



For example:
The author field's type is object.




"_id" : ObjectId("55edfbd11a87d41d987a6dc1"),
"tweet" : "Back in my dorm, yay!",
"uri" : "https://twitter.com/natalylug0/status/640994018529181696",
"date" : "2015-09-08 00:04:17",
"country" : "U.S.A.",
"city" : "Texas",
"state" : "Dallas",
"author" :
"username" : "Nataly",
"uri" : "https://twitter.com/natalylug0",
"screenname" : "natalylug0"




And the other one:
The author field's type is array.




"_id" : ObjectId("55ee3a00e11fbb1030d659fe"),
"author" : [

"username" : "Relapsed Shini",
"uri" : "https://twitter.com/iPictoraL",
"screenname" : "iPictoraL"

],
"tweet" : "@zumbiezuza 😍😍😍💚 ily zoeeeeeeee",
"uri" : "https://twitter.com/iPictoraL/status/641060812140900352",
"date" : "2015-09-08 01:29:42",
"country" : "U.S.A.",
"city" : "Texas",
"state" : "Dallas"



So I executed query like this:



db.getCollection('tweets').find( author: $type: 4 )


And what I get is



Fetched 0 record(s) 


But if execute $type:3 I get 284.116 values which is the same value of size of this collection.



So my question is, how can I filter objects which "author" fields contain arrays.










share|improve this question




























    7














    I have a MongoDb collection contains of 284.116 tweets. The problem is the "author" field in some objects are in object type, but in other objects -this "author" field- are in array type. So the problem is I want to filter which ones are Array, and which ones are Object.



    For example:
    The author field's type is object.




    "_id" : ObjectId("55edfbd11a87d41d987a6dc1"),
    "tweet" : "Back in my dorm, yay!",
    "uri" : "https://twitter.com/natalylug0/status/640994018529181696",
    "date" : "2015-09-08 00:04:17",
    "country" : "U.S.A.",
    "city" : "Texas",
    "state" : "Dallas",
    "author" :
    "username" : "Nataly",
    "uri" : "https://twitter.com/natalylug0",
    "screenname" : "natalylug0"




    And the other one:
    The author field's type is array.




    "_id" : ObjectId("55ee3a00e11fbb1030d659fe"),
    "author" : [

    "username" : "Relapsed Shini",
    "uri" : "https://twitter.com/iPictoraL",
    "screenname" : "iPictoraL"

    ],
    "tweet" : "@zumbiezuza 😍😍😍💚 ily zoeeeeeeee",
    "uri" : "https://twitter.com/iPictoraL/status/641060812140900352",
    "date" : "2015-09-08 01:29:42",
    "country" : "U.S.A.",
    "city" : "Texas",
    "state" : "Dallas"



    So I executed query like this:



    db.getCollection('tweets').find( author: $type: 4 )


    And what I get is



    Fetched 0 record(s) 


    But if execute $type:3 I get 284.116 values which is the same value of size of this collection.



    So my question is, how can I filter objects which "author" fields contain arrays.










    share|improve this question


























      7












      7








      7


      1





      I have a MongoDb collection contains of 284.116 tweets. The problem is the "author" field in some objects are in object type, but in other objects -this "author" field- are in array type. So the problem is I want to filter which ones are Array, and which ones are Object.



      For example:
      The author field's type is object.




      "_id" : ObjectId("55edfbd11a87d41d987a6dc1"),
      "tweet" : "Back in my dorm, yay!",
      "uri" : "https://twitter.com/natalylug0/status/640994018529181696",
      "date" : "2015-09-08 00:04:17",
      "country" : "U.S.A.",
      "city" : "Texas",
      "state" : "Dallas",
      "author" :
      "username" : "Nataly",
      "uri" : "https://twitter.com/natalylug0",
      "screenname" : "natalylug0"




      And the other one:
      The author field's type is array.




      "_id" : ObjectId("55ee3a00e11fbb1030d659fe"),
      "author" : [

      "username" : "Relapsed Shini",
      "uri" : "https://twitter.com/iPictoraL",
      "screenname" : "iPictoraL"

      ],
      "tweet" : "@zumbiezuza 😍😍😍💚 ily zoeeeeeeee",
      "uri" : "https://twitter.com/iPictoraL/status/641060812140900352",
      "date" : "2015-09-08 01:29:42",
      "country" : "U.S.A.",
      "city" : "Texas",
      "state" : "Dallas"



      So I executed query like this:



      db.getCollection('tweets').find( author: $type: 4 )


      And what I get is



      Fetched 0 record(s) 


      But if execute $type:3 I get 284.116 values which is the same value of size of this collection.



      So my question is, how can I filter objects which "author" fields contain arrays.










      share|improve this question















      I have a MongoDb collection contains of 284.116 tweets. The problem is the "author" field in some objects are in object type, but in other objects -this "author" field- are in array type. So the problem is I want to filter which ones are Array, and which ones are Object.



      For example:
      The author field's type is object.




      "_id" : ObjectId("55edfbd11a87d41d987a6dc1"),
      "tweet" : "Back in my dorm, yay!",
      "uri" : "https://twitter.com/natalylug0/status/640994018529181696",
      "date" : "2015-09-08 00:04:17",
      "country" : "U.S.A.",
      "city" : "Texas",
      "state" : "Dallas",
      "author" :
      "username" : "Nataly",
      "uri" : "https://twitter.com/natalylug0",
      "screenname" : "natalylug0"




      And the other one:
      The author field's type is array.




      "_id" : ObjectId("55ee3a00e11fbb1030d659fe"),
      "author" : [

      "username" : "Relapsed Shini",
      "uri" : "https://twitter.com/iPictoraL",
      "screenname" : "iPictoraL"

      ],
      "tweet" : "@zumbiezuza 😍😍😍💚 ily zoeeeeeeee",
      "uri" : "https://twitter.com/iPictoraL/status/641060812140900352",
      "date" : "2015-09-08 01:29:42",
      "country" : "U.S.A.",
      "city" : "Texas",
      "state" : "Dallas"



      So I executed query like this:



      db.getCollection('tweets').find( author: $type: 4 )


      And what I get is



      Fetched 0 record(s) 


      But if execute $type:3 I get 284.116 values which is the same value of size of this collection.



      So my question is, how can I filter objects which "author" fields contain arrays.







      mongodb mongodb-query






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 10 '15 at 23:07









      Blakes Seven

      33.9k86475




      33.9k86475










      asked Sep 10 '15 at 22:42









      Ali Yeşilkanat

      150314




      150314






















          2 Answers
          2






          active

          oldest

          votes


















          20
















          Actually there is a "gotcha" listed in the documentation for $type specifically about arrays:




          When applied to arrays, $type matches any inner element that is of the specified type. Without projection this means that the entire array will match if any element has the right type. With projection, the results will include just those elements of the requested type.




          So that means that rather than detect whether the "element itself" is in array, what is actually being tested is the "inner element" of the array to see what type it is.



          Now the documentation itself suggests this JavaScript test with $where:



          .find( "$where": "return Array.isArray(this.author)" )


          But I think that's pretty horrible as there is a better way.



          The trick is in "dot notation", where you ask for the 0 index element of the array to $exists



          .find( "author.0": "$exists": true )


          Which is just the basic case that if the "0th" element exists then the field is present and the data is therefore an array.



          Once you understand that logical premise then it is pretty simple test. The only thing that cannot be matched by that is a "truly empty" array, in which case you can fall back to the JavaScript alternative if needed. But this can actually use an index, so it would be preferred to use the latter form.






          share|improve this answer


















          • 1




            If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
            – Danielo515
            Jan 25 '18 at 11:07



















          3














          Here's a better way to do what you originally asked; that is to actually check if a certain field holds an array type value:



          .find( "author": "$gte": )


          MongoDB's $type functionality for arrays, though well documented, is IMO inconsistent with all the other $type checks, and obviously doesn't work for this use case, but since around 2.6, you can use the above query to check whether the value is an array (empty or not).



          I say this is "better" than the currently selected answer, because executing code via $where is not recommended, unless standard query constructs truly cannot get the job done.



          To elaborate, $where is not recommended due to performance via lack of ability to use indexes in executed code. More detail: https://docs.mongodb.com/manual/reference/operator/query/where/#considerations



          Also, if you'd like to check for non-empty arrays specifically, use this:



          .find( "author": "$gt": )


          Technically, this one is also better than the current answer's corresponding $exists solution, as the field may have a non-array object with a field named "0", and that would match as a "non-empty array", which is wrong in that case.






          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%2f32512764%2fmongodb-match-an-array-with-type%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            20
















            Actually there is a "gotcha" listed in the documentation for $type specifically about arrays:




            When applied to arrays, $type matches any inner element that is of the specified type. Without projection this means that the entire array will match if any element has the right type. With projection, the results will include just those elements of the requested type.




            So that means that rather than detect whether the "element itself" is in array, what is actually being tested is the "inner element" of the array to see what type it is.



            Now the documentation itself suggests this JavaScript test with $where:



            .find( "$where": "return Array.isArray(this.author)" )


            But I think that's pretty horrible as there is a better way.



            The trick is in "dot notation", where you ask for the 0 index element of the array to $exists



            .find( "author.0": "$exists": true )


            Which is just the basic case that if the "0th" element exists then the field is present and the data is therefore an array.



            Once you understand that logical premise then it is pretty simple test. The only thing that cannot be matched by that is a "truly empty" array, in which case you can fall back to the JavaScript alternative if needed. But this can actually use an index, so it would be preferred to use the latter form.






            share|improve this answer


















            • 1




              If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
              – Danielo515
              Jan 25 '18 at 11:07
















            20
















            Actually there is a "gotcha" listed in the documentation for $type specifically about arrays:




            When applied to arrays, $type matches any inner element that is of the specified type. Without projection this means that the entire array will match if any element has the right type. With projection, the results will include just those elements of the requested type.




            So that means that rather than detect whether the "element itself" is in array, what is actually being tested is the "inner element" of the array to see what type it is.



            Now the documentation itself suggests this JavaScript test with $where:



            .find( "$where": "return Array.isArray(this.author)" )


            But I think that's pretty horrible as there is a better way.



            The trick is in "dot notation", where you ask for the 0 index element of the array to $exists



            .find( "author.0": "$exists": true )


            Which is just the basic case that if the "0th" element exists then the field is present and the data is therefore an array.



            Once you understand that logical premise then it is pretty simple test. The only thing that cannot be matched by that is a "truly empty" array, in which case you can fall back to the JavaScript alternative if needed. But this can actually use an index, so it would be preferred to use the latter form.






            share|improve this answer


















            • 1




              If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
              – Danielo515
              Jan 25 '18 at 11:07














            20












            20








            20








            Actually there is a "gotcha" listed in the documentation for $type specifically about arrays:




            When applied to arrays, $type matches any inner element that is of the specified type. Without projection this means that the entire array will match if any element has the right type. With projection, the results will include just those elements of the requested type.




            So that means that rather than detect whether the "element itself" is in array, what is actually being tested is the "inner element" of the array to see what type it is.



            Now the documentation itself suggests this JavaScript test with $where:



            .find( "$where": "return Array.isArray(this.author)" )


            But I think that's pretty horrible as there is a better way.



            The trick is in "dot notation", where you ask for the 0 index element of the array to $exists



            .find( "author.0": "$exists": true )


            Which is just the basic case that if the "0th" element exists then the field is present and the data is therefore an array.



            Once you understand that logical premise then it is pretty simple test. The only thing that cannot be matched by that is a "truly empty" array, in which case you can fall back to the JavaScript alternative if needed. But this can actually use an index, so it would be preferred to use the latter form.






            share|improve this answer
















            Actually there is a "gotcha" listed in the documentation for $type specifically about arrays:




            When applied to arrays, $type matches any inner element that is of the specified type. Without projection this means that the entire array will match if any element has the right type. With projection, the results will include just those elements of the requested type.




            So that means that rather than detect whether the "element itself" is in array, what is actually being tested is the "inner element" of the array to see what type it is.



            Now the documentation itself suggests this JavaScript test with $where:



            .find( "$where": "return Array.isArray(this.author)" )


            But I think that's pretty horrible as there is a better way.



            The trick is in "dot notation", where you ask for the 0 index element of the array to $exists



            .find( "author.0": "$exists": true )


            Which is just the basic case that if the "0th" element exists then the field is present and the data is therefore an array.



            Once you understand that logical premise then it is pretty simple test. The only thing that cannot be matched by that is a "truly empty" array, in which case you can fall back to the JavaScript alternative if needed. But this can actually use an index, so it would be preferred to use the latter form.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 11 '15 at 3:43

























            answered Sep 10 '15 at 23:07









            Blakes Seven

            33.9k86475




            33.9k86475







            • 1




              If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
              – Danielo515
              Jan 25 '18 at 11:07













            • 1




              If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
              – Danielo515
              Jan 25 '18 at 11:07








            1




            1




            If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
            – Danielo515
            Jan 25 '18 at 11:07





            If your code has a bug and is inserting objects that look like arrays the proposed "author.0": "$exists": true will not work. I'm talking about 0:"bla"
            – Danielo515
            Jan 25 '18 at 11:07














            3














            Here's a better way to do what you originally asked; that is to actually check if a certain field holds an array type value:



            .find( "author": "$gte": )


            MongoDB's $type functionality for arrays, though well documented, is IMO inconsistent with all the other $type checks, and obviously doesn't work for this use case, but since around 2.6, you can use the above query to check whether the value is an array (empty or not).



            I say this is "better" than the currently selected answer, because executing code via $where is not recommended, unless standard query constructs truly cannot get the job done.



            To elaborate, $where is not recommended due to performance via lack of ability to use indexes in executed code. More detail: https://docs.mongodb.com/manual/reference/operator/query/where/#considerations



            Also, if you'd like to check for non-empty arrays specifically, use this:



            .find( "author": "$gt": )


            Technically, this one is also better than the current answer's corresponding $exists solution, as the field may have a non-array object with a field named "0", and that would match as a "non-empty array", which is wrong in that case.






            share|improve this answer

























              3














              Here's a better way to do what you originally asked; that is to actually check if a certain field holds an array type value:



              .find( "author": "$gte": )


              MongoDB's $type functionality for arrays, though well documented, is IMO inconsistent with all the other $type checks, and obviously doesn't work for this use case, but since around 2.6, you can use the above query to check whether the value is an array (empty or not).



              I say this is "better" than the currently selected answer, because executing code via $where is not recommended, unless standard query constructs truly cannot get the job done.



              To elaborate, $where is not recommended due to performance via lack of ability to use indexes in executed code. More detail: https://docs.mongodb.com/manual/reference/operator/query/where/#considerations



              Also, if you'd like to check for non-empty arrays specifically, use this:



              .find( "author": "$gt": )


              Technically, this one is also better than the current answer's corresponding $exists solution, as the field may have a non-array object with a field named "0", and that would match as a "non-empty array", which is wrong in that case.






              share|improve this answer























                3












                3








                3






                Here's a better way to do what you originally asked; that is to actually check if a certain field holds an array type value:



                .find( "author": "$gte": )


                MongoDB's $type functionality for arrays, though well documented, is IMO inconsistent with all the other $type checks, and obviously doesn't work for this use case, but since around 2.6, you can use the above query to check whether the value is an array (empty or not).



                I say this is "better" than the currently selected answer, because executing code via $where is not recommended, unless standard query constructs truly cannot get the job done.



                To elaborate, $where is not recommended due to performance via lack of ability to use indexes in executed code. More detail: https://docs.mongodb.com/manual/reference/operator/query/where/#considerations



                Also, if you'd like to check for non-empty arrays specifically, use this:



                .find( "author": "$gt": )


                Technically, this one is also better than the current answer's corresponding $exists solution, as the field may have a non-array object with a field named "0", and that would match as a "non-empty array", which is wrong in that case.






                share|improve this answer












                Here's a better way to do what you originally asked; that is to actually check if a certain field holds an array type value:



                .find( "author": "$gte": )


                MongoDB's $type functionality for arrays, though well documented, is IMO inconsistent with all the other $type checks, and obviously doesn't work for this use case, but since around 2.6, you can use the above query to check whether the value is an array (empty or not).



                I say this is "better" than the currently selected answer, because executing code via $where is not recommended, unless standard query constructs truly cannot get the job done.



                To elaborate, $where is not recommended due to performance via lack of ability to use indexes in executed code. More detail: https://docs.mongodb.com/manual/reference/operator/query/where/#considerations



                Also, if you'd like to check for non-empty arrays specifically, use this:



                .find( "author": "$gt": )


                Technically, this one is also better than the current answer's corresponding $exists solution, as the field may have a non-array object with a field named "0", and that would match as a "non-empty array", which is wrong in that case.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 1 '17 at 18:52









                Ciabaros

                486




                486



























                    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.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • 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%2f32512764%2fmongodb-match-an-array-with-type%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

                    Use pre created SQLite database for Android project in kotlin

                    Darth Vader #20

                    Ondo