@Nullable
  protected GetResult extractGetResult(
      final UpdateRequest request,
      long version,
      final Map<String, Object> source,
      XContentType sourceContentType,
      @Nullable final BytesReference sourceAsBytes) {
    if (request.fields() == null || request.fields().length == 0) {
      return null;
    }
    boolean sourceRequested = false;
    Map<String, GetField> fields = null;
    if (request.fields() != null && request.fields().length > 0) {
      SourceLookup sourceLookup = new SourceLookup();
      sourceLookup.setNextSource(source);
      for (String field : request.fields()) {
        if (field.equals("_source")) {
          sourceRequested = true;
          continue;
        }
        Object value = sourceLookup.extractValue(field);
        if (value != null) {
          if (fields == null) {
            fields = newHashMapWithExpectedSize(2);
          }
          GetField getField = fields.get(field);
          if (getField == null) {
            getField = new GetField(field, new ArrayList<Object>(2));
            fields.put(field, getField);
          }
          getField.getValues().add(value);
        }
      }
    }

    // TODO when using delete/none, we can still return the source as bytes by generating it (using
    // the sourceContentType)

    return new GetResult(
        request.index(),
        request.type(),
        request.id(),
        version,
        true,
        sourceRequested ? sourceAsBytes : null,
        fields);
  }