2014-05-08 10 views
9

Mam dokument, który jest ustawienie tak:MongoDB znaleźć wewnątrz sub tablicy

{ 
    _id : ObjectId(), 
    info : [ 
     [ 
      1399583281000, 
      20.13 
     ], 
     [ 
      1399583282000, 
      20.13 
     ], 
     [ 
      1399583283000, 
      20.13 
     ], 
     [ 
      1399583285000, 
      20.13 
     ], 
     [ 
      1399583286000, 
      20.13 
     ] 
    ] 
} 

Dane te mogą być rozłożone w wielu dokumentach. Ogólnie każdy dokument zawiera dane w informacji przez 59 okresów (w sekundach).

Co chcę zrobić, to uzyskać wszystkie dane informacyjne, w których znacznik czasu jest większy niż określony czas.

Jakieś pomysły, jak to zrobić?

Dziękuję

EDIT:

Tak, znalazłem, że to wydaje się powrót wszystkich dokumentów:

db.infos.find({ 
    info:{ 
     $elemMatch:{ 
     0:{ 
      $gt:1399583306000 
     } 
     } 
    } 
}) 

Ale może muszę to wykorzystać w zapytaniu kruszywa ? aby zwrócić tylko wszystkie wartości?

Odpowiedz

8

Twój właściwy tor, ale jest kilka rzeczy do zapamiętania tutaj, oprócz części, w której zagnieżdżone tablice (a zwłaszcza z anonimowymi kluczami) nie są dokładnie doskonałym sposobem przechowywania rzeczy, ale tak długo, jak konsekwentnie znać pozycję, która powinna być rozsądnie w porządku.

Istnieje wyraźna różnica między dopasowaniem dokumentów i dopasowaniem "elementów tablicy". Chociaż twoja obecna wartość nie pasowałaby (twoja wartość wyszukiwania nie mieści się w granicach dokumentu), jeśli wartość rzeczywiście była prawidłowa twoje zapytanie poprawnie pasuje do "dokumentu" tutaj, który zawiera pasujący element w tablicy.

„Dokument” zawiera wszystkie z elementów tablicy, nawet te, które nie pasują do siebie, ale warunek mówi „dokument” pasuje, więc to nie jest zwracana. Jeśli chcesz tylko dopasowywanie „elementy” następnie użyć .aggregate() zamiast:

db.infos.aggregate([ 
     // Still match the document 
     { "$match": { 
      "info": { 
       "$elemMatch": { "0": {"$gte": 1399583285000} } 
      } 
     }}, 

     // unwind the array for the matched documents 
     { "$unwind": "$info" }, 

     // Match only the elements 
     { "$match": { "info.0": { "$gte": 1399583285000 } } }, 

     // Group back to the original form if you want 
     { "$group": { 
      "_id": "$_id", 
      "info": { "$push": "$info" } 
     }} 

    ]) 

I zwraca tylko te elementy, które dopasowane warunek:

{ 
    "_id" : ObjectId("536c1145e99dc11e65ed07ce"), 
    "info" : [ 
      [ 
        1399583285000, 
        20.13 
      ], 
      [ 
        1399583286000, 
        20.13 
      ] 
    ] 
} 

Albo oczywiście jeśli tylko kiedykolwiek spodziewać Jeden element do dopasowania, następnie można po prostu użyć projekcji z .find()**:

db.infos.find(
    { 
     "info":{ 
      "$elemMatch":{ 
      "0": { 
       "$gt": 1399583285000 
      } 
      } 
     } 
    }, 
    { 
     "info.$": 1 
    } 
) 

Ale z określeniem jak $gt jesteś prawdopodobne, aby uzyskać wielokrotne ciosy w dokumencie więc łączna podejście będzie bezpieczniej biorąc pod uwagę, że operator positional $ będzie jedynie do zwrotu pierwszy mecz.

+0

To jest świetne! Jedną z rzeczy, którą odkryłem jest oddzielenie przez '_id', to nie jedna duża tablica zawierająca tablice. – dzm

+0

@dave "Separator" jest według wartości, której używasz w polu '_id' instrukcji' $ group', więc jest to, co chcesz, lub 'null' dla wszystkiego w kolekcji. Ale wydawało mi się, że po przefiltrowaniu tego dokumentu. Użyj jak chcesz. –

+0

Rozumiem, mogę po prostu 'null'' _id', perfect. Dziękuję Ci! – dzm