2016-01-26 2 views
4

Я следующий документ в Монго:Получить значение из встроенного документа Монго Java

> { "_id": ObjectId("569afce4b932c542500143ec"),  
> "date": "2016-1-17T2:31:0Z",  
> "day": NumberInt(17),  
> "model1": { 
>  "date": "2016-01-17T02:31+0000", 
>  "MondayModel": { 
>  "gtxdotdot": { 
>   "xdotdot": 0, 
>   "xdot": 0 
>  }, 
>  "lsxdotdot": { 
>   "xdotdot": 0, 
>   "xdot": 0 
>  }, 
>  "gtxdot": { 
>   "xdotdot": 0, 
>   "xdot": 0 
>  }, 
>  "lsxdot": { 
>   "xdotdot": 0, 
>   "xdot": 0 
>  }, 
>  "modeldotdot": { 
>   "mean": 0, 
>   "sdvar": 0 
>  }, 
>  "modeldot": { 
>   "mean": 0, 
>   "sdvar": 0 
>  } 
>  } 
>  } 

Я хочу как найти этот документ и извлечь только значения model1.MondayModel.gtxdotdot.xdotdot/xdot/mean/sdvar ...

Мой текущий код делает так со следующим:

MongoCursor<Document> back = collection.find(and(eq("topic",topic),eq("sp",sp))).limit(1).iterator(); 
if (back.hasNext()) 
{ 
    Document doc = back.next(); 
    Document tmpddc1 = (Document)doc.get("model1"); 
    Document tmpddc2 = (Document)tmpddc1.get("MondayModel"); 

    Document tmpddc3 = (Document)tmpddc2.get("gtxdotdot"); 
    gtxdotdotXdotdot = tmpddc3.getDouble("xdotdot"); 
    gtxdotdotXdot = tmpddc3.getDouble("xdot"); 

      tmpddc3 = (Document)tmpddc2.get("lsxdotdot"); 
    lsxdotdotXdotdot = tmpddc3.getDouble("xdotdot"); 
    lsxdotdotXdot = tmpddc3.getDouble("xdot"); 

      tmpddc3 = (Document)tmpddc2.get("gtxdot"); 
    gtxdotXdotdot = tmpddc3.getDouble("xdotdot"); 
    gtxdotXdot = tmpddc3.getDouble("xdot");    

      tmpddc3 = (Document)tmpddc2.get("lsxdot"); 
    lsxdotXdotdot = tmpddc3.getDouble("xdotdot"); 
    lsxdotXdot = tmpddc3.getDouble("xdot"); 


      tmpddc3 = (Document)tmpddc2.get("modeldotdot"); 
    modeldotdotXmean = tmpddc3.getDouble("mean"); 
    modeldotdotXsdvar = tmpddc3.getDouble("sdvar");    

      tmpddc3 = (Document)tmpddc2.get("modeldot"); 
    modeldotXmean = tmpddc3.getDouble("mean"); 
    modeldotXsdvar = tmpddc3.getDouble("sdvar");       

} 

Вместо бегов, что он документ (как описано выше), есть ли способ, чтобы получить значение, используя точечную нотацию [model1.MondayModel.gtxdotdot.xdotdot] ? Что-то вроде:

double value = doc.getDouble("model1.MondayModel.gtxdotdot.xdotdot"); 

ответ

0

Я не думаю, что вы можете использовать точечную нотацию напрямую, но вы можете создать свою собственную вспомогательную функцию.

Решение 1: получить поле с помощью точечной нотации

public static Object getWithDotNotation(Document document, String dots) 
    throws MongoException{ 

    String[] keys = dots.split("\\."); 
    Document doc = document; 

    for(int i = 0; i < keys.length - 1; i++){ 
     Object o = doc.get(keys[ i ]); 
     if(o == null || !(o instanceof Document)){ 
      throw new MongoException(String.format( 
        "Field '%s' does not exist or s not a Document", keys[ i ])); 
     } 
     doc = (Document) o; 
    }//end for 

    return doc.get(keys[ keys.length - 1 ]); 
} 

Вы можете использовать его как это:

String dotNotation = "model1.MondayModel.gtxdotdot.xdotdot"; 

FindIterable<Document> projection = mongoColl.find() 
    .projection(fields(include(dotNotation))); 

Double value = (Double) getWithDotNotation(projection.first(), dotNotation); 

System.out.println(value); // result: 0.0 

Это упростит ваш код много. Единственные, что для ухода за являются:

  • , если вы не уверены, вы точечной нотации, используйте try catch блок
  • метод getWithDotNotation может возвращать нуль
  • быть осторожным принудительными слепками, используйте его только если вы на 100% уверены в типе ваших данных (здесь Double).

Решение 2: расплющить ваш документ

public static Document flattenDoc(Document document){ 

    Document flattened = new Document(); 
    Queue<Pair<String, Document>> queue = new ArrayDeque<>(); 
    queue.add(new Pair<>("", document)); 

    while(!queue.isEmpty()){ 
     Pair<String, Document> pair = queue.poll(); 
     String key = pair.getKey(); 
     for(Map.Entry<String, Object> entry : pair.getValue().entrySet()){ 
      if(entry.getValue() instanceof Document){ 
       queue.add(new Pair<>(key + entry.getKey() + ".", (Document) entry.getValue())); 

      }else{ 
       flattened.put(key + entry.getKey(), entry.getValue()); 

      } 
     }//end for 
    } 

    return flattened; 
} 

С вашими данными выборки, результат flattenDoc следующий:

Document{{_id=569afce4b932c542500143ec, 
date=2016-1-17T2:31:0Z, 
day=17, 
model1.date=2016-01-17T02:31+0000, 
model1.MondayModel.gtxdotdot.xdotdot=0.0, 
model1.MondayModel.gtxdotdot.xdot=0.0, 
model1.MondayModel.lsxdotdot.xdotdot=0.0, 
model1.MondayModel.lsxdotdot.xdot=0.0, 
model1.MondayModel.gtxdot.xdotdot=0.0, 
model1.MondayModel.gtxdot.xdot=0.0, 
model1.MondayModel.lsxdot.xdotdot=0.0, 
model1.MondayModel.lsxdot.xdot=0.0, 
model1.MondayModel.modeldotdot.mean=0.0, 
model1.MondayModel.modeldotdot.sdvar=0.0, 
model1.MondayModel.modeldot.mean=0.0, 
model1.MondayModel.modeldot.sdvar=0.0}} 

Таким образом, вы можете использовать getDouble("model1.MondayModel.gtxdotdot.xdotdot") непосредственно. Этот подход может быть более эффективным, если вам нужно получить доступ ко всем полям.

Смежные вопросы