5

How can I get the length of characters from a field that is nested in another field? and it is in an array. eg:

{
    "_id" : ObjectId("687e1db"),
    "content" : {
        "ods" : "1102223000241",
        "startDate" : ISODate("2017-05-11T12:00:00Z"),
        "classes" : [
            {
              "driveNumber" : "9999078900007091",
              "number" : "00107605829357",
              "sId" : "0000000005009593"
            }
        ],
         "user" : "SoftLogic",
    },
    "level" : 2
}

and I want to get a sample in the content.classes.number, where there are more than 16 characters in the field.

when making a request I was guided by String field value length in mongoDB

Either this request is not suitable for this situation, or I am doing something wrong.

db.Basis.find({
    "content.classes.number": { "$exists": true }, 
    "$expr": { "$gt": [ { "$strLenCP": "$content.classes.number" }, 16 ] }})

I get the error: https://gyazo.com/d2849406d36364de94d6ea89eff1c2b6

I tried not only such options.

UPD mongo version 3.4.3

6
  • 2
    The error means what it says in that "classes" is actually an array, therefore any field path expression like "$content.classes.number" also produces an array of the matching values. Your question only shows a single array member, so it's unclear if you use of an array in the structure is incorrect and it should be singular, or whether you actually mean this to be an array and there can indeed be multiple members. Commented Apr 9, 2019 at 8:03
  • 3
    If it's actually supposed to be an array then the $expr should be "$expr": { "$anyElementTrue": { "$map": { "input": "$content.classes.number", "in": { "$gt": [ { "$strLenCP": "$$this" }, 16 ] } } } }. Which is also basically the same as "$where": "this.content.classes.some(e => e.number.length > 16)" as the alternate $where expression. $expr should process faster than $where though the syntax is more terse. Commented Apr 9, 2019 at 8:09
  • @NeilLunn thank! not just one item. so you are certainly right, the answer is: "$expr": { "$anyElementTrue": { "$map": { "input": "$content.classes.number", "in": { "$gt": [ { "$strLenCP": "$$this" }, 16 ] } } } } . It came up for version 3.6.9. But it turned out that it is necessary to install on version 3.4.3 and there gyazo.com/8031da7305191d3bdfd02ca87abafdd5 Commented Apr 9, 2019 at 17:31
  • Why you cannot update your version? Newer version are always "cubby". So it is better to use the upgraded version. Commented Apr 9, 2019 at 17:41
  • Yes, I agree. This version is not local to me, it is in production. need to understand whether there is data that meets these conditions. Commented Apr 9, 2019 at 20:38

1 Answer 1

3

content.classes.number is an array field not a string and that's why your query could not work.

One solution here is to use $arrayElemAt operator but don't know which element you want to check with. But for instance, I am taking the 0th element here.

db.Basis.find({
  "content.classes.number": { "$exists": true }, 
  "$expr": { "$gt": [{ "$strLenCP": { "$arrayElemAt": ["$content.classes.number", 0] }}, 16 ] }
})
Sign up to request clarification or add additional context in comments.

7 Comments

Bit of a leap to presume the array only has one element. I know the question only shows one, but an Array should be presumed to mean "an Array" and be treated as such. On the other hand if a question specifically asked "first array element", then $arrayElemAt would be fine. But it's very possibly not the actual case. There are operators for process ALL possible array elements. See the comment on the question.
@NeilLunn Hmm I know the OP is bit unclear about his question. That's why I wrote but don't know which element you want to check with and waiting for his reply. :-) And your comment I think should be the answer because it seems to perfect as OP needed.
@Anthony Winzlet NeilLunn is definitely right. but unfortunately with version 3.4.3 gyazo.com/8031da7305191d3bdfd02ca87abafdd5
@СомаТха Yes Neil Lunn can never be wrong. I am just waiting for your reply. I will update my answer as your need but you need to be more clear.
@Anthony Winzlet Your answer really helped, but it didn’t touch all the cases in the array. it also turned out that the version in production 3.4.3 (
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.