MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Mongo Query Вложени стойности на полета с неизвестни родителски ключове на две нива

Намаляването на картата ви позволява да обработвате именувани ключове, но агрегирането е начинът за ефективни заявки.

Трябва да моделирате данните като масив от вградени документи за рамка за агрегиране.

Предоставих ви два варианта. Можете да ги тествате за вашия набор от данни и да видите кой работи по-добре за вас.

Нещо като

"v":[
  {
    "minute":1,
    "seconds":[
      {
        "second":54,
        "data":{
         "field1":7.373158,
         "entry_id":4635,
         "field3":0.19,
         "field2":88
       }
      }
    ]
  },
  {
    "minute":2,
    "seconds":...
  }
]

Сега можете лесно да правите заявки за елементи, които имат показания на сензора:"field1">2.

db.col.aggregate(
  [{"$match":{"v.seconds.data.field1":{"$gt":2}}},
   {"$unwind":"$v"}, 
   {"$match":{"v.seconds.data.field1":{"$gt":2}}},
   {"$unwind":"$v.seconds"}, 
   {"$match":{"v.seconds.data.field1":{"$gt":2}}},
   {"$project":{"data":"$v.seconds.data"}}]
)

Като алтернатива можете да разделите документите по минути. Нещо като

"v":[
  {
    "second":1,
    "data":{
       "field1":7.373158,
       "entry_id":4635,
       "field3":0.19,
       "field2":88
     }
  },
  {
     "second":2,
     "data":...
  }
]

Вече можете да правите заявки като ( с индекс на v.data.field1 )

db.col.aggregate(
  [{"$match":{"v.data.field1":{"$gt":2}}},
   {"$unwind":"$v"}, 
   {"$match":{"v.data.field1":{"$gt":2}}},
   {"$project":{"data":"$v.data"}}]
)

Можете да правите заявки за елементи, които имат показания на сензора:"field1">2 и "field3">5

Използване на първата структура

db.col.aggregate(
  [{"$match":{"v":{"$elemMatch":{"seconds": {$elemMatch:{"field1":{$gt":2},"field3":{$gt":5}}}}}}},
  {"$unwind":"$v"}, 
    {"$match":{"v.seconds": {$elemMatch:{"field1":{$gt":2},"field3":{$gt":5}}}}},
  {"$unwind":"$v.seconds"}, 
  {"$project":{"data":"$v.seconds.data"}}]
)

Използване на втора структура

db.col.aggregate(
  [{"$match":{"v.data":{$elemMatch:{"field1":{$gt":2},"field3":{$gt":5}}}}},
  {"$unwind":"$v"}, 
  {"$match":{"v.data.field1":{"$gt":2},"v.data.field3":{"$gt":5} }},
  {"$project":{"data":"$v.data"}}]
)

Mongo Актуализация 3.6

$match с $expr който приема израз на агрегиране.

$gt > 0 - обобщаващ израз за проверка къде сумата от всички съвпадащи критерии за секунди в минута е по-голяма от 0

$objectToArray за преобразуване на именуваните ключове в двойка ключ стойност, последвана от $filter секунди по входни критерии и изходен номер на съответстващ запис на секунди.

db.testcol.aggregate(
{"$match":{
  "$expr":{
    "$gt":[
      {"$sum":{
        "$map":{
          "input":{"$objectToArray":"$v"},
          "as":"secondsofminute",
          "in":{
            "$size":{
              "$filter":{
                "input":{"$objectToArray":"$$secondsofminute.v"},
                "as":"seconds",
                "cond":{"$gt":["$$seconds.v.field2",2]}
              }
            }
          }
        }
      }},
    0]
  }
}})

Mongo Актуализация 3.4 - Замяна на $expr с $redact

db.col.aggregate(
 {"$redact":{
  "$cond":{
    "if":{
      "$gt":[
        {"$sum":{
          "$map":{
            "input":{"$objectToArray":"$v"},
            "as":"secondsofminute",
            "in":{
              "$size":{
                "$filter":{
                  "input":{"$objectToArray":"$$secondsofminute.v"},
                  "as":"seconds",
                  "cond":{"$gt":["$$seconds.v.field2",2]}
                }
              }
            }
          }
        }},
        0]
    },
   "then":"$$KEEP",
   "else":"$$PRUNE"
  }
}})



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. mongodb клъстер с ELB крайна точка като dns

  2. Индекс на поддокумента в mongo

  3. Няма достъп до свойството на обекта на отговора на Mongoose

  4. Разгръщане и конфигуриране на MongoDB Shards с Ansible

  5. MongoDB, Mongoose:Как да намеря поддокумент в намерен документ?