def find_view(request):
  "View for finding metrics matching a given pattern"

  queryParams = request.GET.copy()
  queryParams.update(request.POST)

  format = queryParams.get('format', 'treejson')
  leaves_only = queryParamAsInt(queryParams, 'leavesOnly', 0)
  local_only = queryParamAsInt(queryParams, 'local', 0)
  wildcards = queryParamAsInt(queryParams, 'wildcards', 0)

  tzinfo = pytz.timezone(settings.TIME_ZONE)
  if 'tz' in queryParams:
    try:
      value = queryParams['tz']
      tzinfo = pytz.timezone(value)
    except pytz.UnknownTimeZoneError:
      pass
    except Exception as e:
      raise InputParameterError(
        'Invalid value {value} for param tz: {err}'
        .format(value=repr(value), err=str(e)))

  if 'now' in queryParams:
    try:
      value = queryParams['now']
      now = parseATTime(value, tzinfo)
    except Exception as e:
      raise InputParameterError(
        'Invalid value {value} for param now: {err}'
        .format(value=repr(value), err=str(e)))
  else:
    now = datetime.now(tzinfo)

  if 'from' in queryParams and str(queryParams['from']) != '-1':
    try:
      value = queryParams['from']
      fromTime = int(epoch(parseATTime(value, tzinfo, now)))
    except Exception as e:
      raise InputParameterError(
        'Invalid value {value} for param from: {err}'
        .format(value=repr(value), err=str(e)))
  else:
    fromTime = -1

  if 'until' in queryParams and str(queryParams['until']) != '-1':
    try:
      value = queryParams['until']
      untilTime = int(epoch(parseATTime(value, tzinfo, now)))
    except Exception as e:
      raise InputParameterError(
        'Invalid value {value} for param until: {err}'
        .format(value=repr(value), err=str(e)))
  else:
    untilTime = -1

  nodePosition = queryParamAsInt(queryParams, 'position', -1)
  jsonp = queryParams.get('jsonp', False)
  forward_headers = extractForwardHeaders(request)

  if fromTime == -1:
    fromTime = None
  if untilTime == -1:
    untilTime = None

  automatic_variants = queryParamAsInt(queryParams, 'automatic_variants', 0)

  try:
    query = str(queryParams['query'])
  except KeyError:
    raise InputParameterError('Missing required parameter \'query\'')

  if query == '':
    raise InputParameterError('Required parameter \'query\' is empty')

  if '.' in query:
    base_path = query.rsplit('.', 1)[0] + '.'
  else:
    base_path = ''

  if format == 'completer':
    query = query.replace('..', '*.')
    if not query.endswith('*'):
      query += '*'

    if automatic_variants:
      query_parts = query.split('.')
      for i,part in enumerate(query_parts):
        if ',' in part and '{' not in part:
          query_parts[i] = '{%s}' % part
      query = '.'.join(query_parts)

  try:
    matches = list(STORE.find(
      query, fromTime, untilTime,
      local=local_only,
      headers=forward_headers,
      leaves_only=leaves_only,
    ))
  except Exception:
    log.exception()
    raise

  log.info('find_view query=%s local_only=%s matches=%d' % (query, local_only, len(matches)))
  matches.sort(key=lambda node: node.name)
  log.info("received remote find request: pattern=%s from=%s until=%s local_only=%s format=%s matches=%d" % (query, fromTime, untilTime, local_only, format, len(matches)))

  if format == 'treejson':
    profile = getProfile(request)
    content = tree_json(matches, base_path, wildcards=profile.advancedUI or wildcards)
    response = json_response_for(request, content, jsonp=jsonp)

  elif format == 'nodelist':
    content = nodes_by_position(matches, nodePosition)
    response = json_response_for(request, content, jsonp=jsonp)

  elif format == 'pickle':
    content = pickle_nodes(matches)
    response = HttpResponse(content, content_type='application/pickle')

  elif format == 'msgpack':
    content = msgpack_nodes(matches)
    response = HttpResponse(content, content_type='application/x-msgpack')

  elif format == 'json':
    content = json_nodes(matches)
    response = json_response_for(request, content, jsonp=jsonp)

  elif format == 'completer':
    results = []
    for node in matches:
      node_info = dict(path=node.path, name=node.name, is_leaf=str(int(node.is_leaf)))
      if not node.is_leaf:
        node_info['path'] += '.'
      results.append(node_info)

    if len(results) > 1 and wildcards:
      wildcardNode = {'name' : '*'}
      results.append(wildcardNode)

    response = json_response_for(request, { 'metrics' : results }, jsonp=jsonp)

  else:
    return HttpResponseBadRequest(
        content="Invalid value for 'format' parameter",
        content_type='text/plain')

  response['Pragma'] = 'no-cache'
  response['Cache-Control'] = 'no-cache'
  return response