Запрос длины строки во вложенном массиве - PullRequest
0 голосов
/ 05 марта 2019

json, который я возвращаю, выглядит так:

{
  "_id" : "id",
  "_class" : "ClassName",
  "key" : [ 
    {
      "_id" : "keyId",
      "array" : [ 
        {
          "arrKey" : "value"
        }
      ]
    }
  ]
}

Я пытаюсь выполнить запрос на основе key.array.arrKey[0].value.length()?Массив должен всегда иметь только одно значение.

Я не уверен, нужно ли мне находить или объединять и сопоставлять, но ниже моя попытка сделать этот запрос.

var cursor = db.getCollection('collection').find( {
    key.array.arrKey[0].value.length: {$gt: 5} 
});

1 Ответ

0 голосов
/ 05 марта 2019

Вы можете использовать $strLenCP в пределах $expr и некоторую осторожную обработку при обработке массивов:

db.collection.find({
  "$expr": {
    "$anyElementTrue": {
      "$map": {
        "input": {
          "$reduce": {
            "input": "$key.array.arrKey",
            "initialValue": [],
            "in": { "$concatArrays": [ "$$value", "$$this" ] }
          }
        },
        "in": { "$gte": [ { "$strLenCP": "$$this" }, 5 ] }
      }
    }
  }
})

Если у вас MongoDB старше чем3.6 вместо этого можно использовать $where:

db.collection.find({
  "$where": function() {
     return this.key.reduce((o,e) => o.concat(e.array.map(a => a.arrKey)), [])
       .some(e => e.length >= 5);
  }
})

Оба следуют одному и тому же принципу доступа к внутренним элементам массива путем «объединения» в один массив строк с последующим тестированием этих элементов.чтобы увидеть, соответствуют ли они требованиям к длине.


Следующее необходимо для предотвращения неправильных ответов

ПРИМЕЧАНИЕ : прежде чем кто-либо еще прыгнет сюда и скажет «Эй, ты не можешь просто сделать это:»

db.collection.find({
  "$expr": { "$gte": [ { "$strLenCP": "$key.array.arrKey" }, 5 ] }
})

Тогда НЕТ, вы не можете , и причина очень проста - посмотретьпри чем это запись выражения агрегации фактически делает :

db.collection.aggregate([
  { "$project": {
    "value": "$key.array.arrKey"
  }}
])

Возвращает:

{ "_id" : "id", "value" : [ [ "value" ] ] }

Таким образом, возвращаемое значение "$key.array.arrKey" НЕ является "строкой""value" но вместо этого это вложенный массив, как показано выше.Следовательно, уменьшает и конкатенацию массива до одного массива строк, а затем map операция над этими элементами массива для проверки каждого элемента .

Именно поэтому оба выражения агрегации И в выражении JavaScript следуют одному и тому же логическому шаблону.Поскольку "$key.array.arrKey" видит совершенно иную картину того, что .find({ "key.array.arrKey": { "$exists: true } }) может делать.

Выражения агрегации и операторы запросов работают совсем по-другому .

Отмечая, конечно, что поиск строк длиннее 6 (или любой длины, превышающей фактическую строку):

 db.collection.find({
   "$expr": { "$gte": [ { "$strLenCP": "$key.array.arrKey" }, 6 ] }
 })

вернет поставленный документ в вопросе с ошибкой .

Обратите также внимание, что в этом случае $strLenCP фактически сравнивает «строковое» представление массива, включая скобки [] ирасстояние.Что, конечно, неверно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...