code: func (t *SimpleChaincode) queryMarblesByOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
  
  	//   0
  	// "bob"
  	if len(args) < 1 {
  		return shim.Error("Incorrect number of arguments. Expecting 1")
  	}
  
  	owner := strings.ToLower(args[0])
  
  	queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"marble\",\"owner\":\"%s\"}}", owner)
  
  	queryResults, err := getQueryResultForQueryString(stub, queryString)
  	if err != nil {
  		return shim.Error(err.Error())
  	}
  	return shim.Success(queryResults)
  }
docs: // =======Rich queries =========================================================================
  // Two examples of rich queries are provided below (parameterized query and ad hoc query).
  // Rich queries pass a query string to the state database.
  // Rich queries are only supported by state database implementations
  //  that support rich query (e.g. CouchDB).
  // The query string is in the syntax of the underlying state database.
  // With rich queries there is no guarantee that the result set hasn't changed between
  //  endorsement time and commit time, aka 'phantom reads'.
  // Therefore, rich queries should not be used in update transactions, unless the
  // application handles the possibility of result set changes between endorsement and commit time.
  // Rich queries can be used for point-in-time queries against a peer.
  // ============================================================================================
  // ===== Example: Parameterized rich query =================================================
  // queryMarblesByOwner queries for marbles based on a passed in owner.
  // This is an example of a parameterized query where the query logic is baked into the chaincode,
  // and accepting a single query parameter (owner).
  // Only available on state databases that support rich query (e.g. CouchDB)
  // =========================================================================================