code: func checkZoomExpr(expr string) error {
  	sq := strings.TrimSpace(expr)
  	if sq == "" {
  		return nil
  	}
  	fields := strings.Fields(sq)
  	if len(fields) == 1 {
  		return nil
  	}
  	var pos []int
  	for k, v := range fields {
  		if geo.IsLocMapPredicate(v) {
  			pos = append(pos, k)
  		}
  	}
  	// Did we find several "map:" predicates?
  	if len(pos) > 1 {
  		return fmt.Errorf("map predicate should be unique. See https://camlistore.org/doc/search-ui")
  	}
  	for _, v := range pos {
  		// does it have an "or" following?
  		if v < len(fields)-1 && fields[v+1] == "or" {
  			return fmt.Errorf(`map predicate with logical "or" forbidden. See https://camlistore.org/doc/search-ui`)
  		}
  		// does it have a preceding "or"?
  		if v > 0 && fields[v-1] == "or" {
  			return fmt.Errorf(`map predicate with logical "or" forbidden. See https://camlistore.org/doc/search-ui`)
  		}
  	}
  	return nil
  }
docs: // checkZoomExpr verifies that expr does not violate the rules about the map
  // predicate, which are:
  // 1) only one map predicate per expression
  // 2) since it is interpreted as a logical "and" to the rest of the expression,
  // logical "or"s around it are forbidden.
  // To be complete we should strip any potential parens around the map
  // predicate itself. But if we start concerning ourselves with such details, we
  // should switch to using a proper parser, like it is done server-side.