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

  • 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*. – Neil Lunn Apr 09 '19 at 08: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*. – Neil Lunn Apr 09 '19 at 08: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 https://gyazo.com/8031da7305191d3bdfd02ca87abafdd5 – Сома Тха Apr 09 '19 at 17:31
  • Why you cannot update your version? Newer version are always "cubby". So it is better to use the upgraded version. – Ashh Apr 09 '19 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. – Сома Тха Apr 09 '19 at 20:38
  • So the [`$expr`](https://docs.mongodb.com/manual/reference/operator/query/expr/) documentation does actually tell you *"New in version 3.6."*, which is why the two cases shown above since if your MongoDB version is **NOT 3.6** or above, then what you wan't is the `$where` expression instead. Note that 3.4 releases will no longer have official support in less than 5 months from the date of this post. – Neil Lunn Apr 14 '19 at 00:05

1 Answers1

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 ] }
})
Ashh
  • 44,693
  • 14
  • 105
  • 132
  • 2
    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. – Neil Lunn Apr 09 '19 at 08:13
  • 1
    @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. – Ashh Apr 09 '19 at 09:34
  • @Anthony Winzlet NeilLunn is definitely right. but unfortunately with version 3.4.3 https://gyazo.com/8031da7305191d3bdfd02ca87abafdd5 – Сома Тха Apr 09 '19 at 17:36
  • @СомаТха 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. – Ashh Apr 09 '19 at 17:39
  • @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 ( – Сома Тха Apr 09 '19 at 20:41
  • @СомаТха If you are using latest mongodb version then use the query mentioned in the above comments by Neil – Ashh Apr 10 '19 at 05:34
  • @Anthony Winzle no, not the last. 3.4.3 – Сома Тха Apr 10 '19 at 20:57