1

I'm making the transition from Contacts API to People API as required by Google. I'm very surprised by the lack of examples online but I can now create, delete and modify/update (thanks to the reply by @Tanaike's reply to Omar F. here: Cannot update contactusgin People api using Google Apps Script) a contact, with delete and modify via iterating through People.People.Connections.List(), with its max of 100 results (from the Apps Script sample here: https://developers.google.com/people/quickstart/apps-script).

But I have about 12,000 contacts and need to use (I assume) People.People.searchContacts(). I haven't found any Apps Script examples and the documentation is all in Java, which I don't know how to translate to Apps Script:

...

// Send search request
SearchResponse response = peopleService.people().searchContacts()
    .setQuery("query")
    .setReadMask("names,emailAddresses")
    .execute();

or "Protocol" which is similarly not useful (for me - I've tried!):

...
// Send search request after several seconds
GET /v1/people:searchContacts?query=query&readMask=names,emailAddresses HTTP/1.1
Host: people.googleapis.com

My best guess to date using Google Drive Query Parameter style since the People API link from this page (https://developers.google.com/people/v1/query-parameters) doesn't seem to help:

let searchResp = People.People.searchContacts(
    "phoneNumbers contains 5632",
    { readMask: "names,phoneNumbers,addresses,emailAddresses" }
  );

let personBob = searchResp.results.find(p =>
    p.names[0].displayName.includes("Bob Q22222")
  );

So after spending an embarrassing amount of time getting to this point, I'm throwing in the towel and hoping someone can give an example of getting a searchResponse via People.People.searchContacts() to show what

  1. A search query looks like and
  2. What a readMask looks like.

I understand that the searchResponse.results is just an array of People and should be fine from there.

Thank you and I hope this wasn't too waffly (baffled non-programmer for our little husband & wife business). ~


Edit: Almost there

Modified from Rafi's reply, this works from a form-attached Appscript file, which is what I want but it's not retrieving all results, see further below):

function run() {
  let query = "Q12755";
  let found = People.People.searchContacts({
    "query": query,
    "readMask": "names,addresses,emailAddresses,phoneNumbers"
  });

  if (found.results) {
    for (i = 0; i < found.results.length; i++) {
      let thisResult = found.results[i];
      Logger.log(`Result ${i}: ${thisResult.person.names[0].displayName}`);
    }
  } else {
    Logger.log(`No results for ${query}`);
  }
}

...but, it's not picking up all of the results.

The test function and result for "Q12755" query: The test function and result for "Q12755" query

Two results for that string in Google Contacts: Two results for that string in Google Contacts

And the same two results on my phone: And the same two results on my phone

Any idea why not all results are being retrieved? I've tested several queries and it consistently misses results. All (I believe) of the Contacts tested have been created via an Appscript script via the deprecating Contacts API.

P.S. I might add that it's not an issue with it only retrieving one result. In other cases where there "should" be like 20 results, in has retrieved half a dozen or so.

P.P.S. A "warmup" of the cache is recommended/required, and I'm assuming the updated script below does that okay. There's no difference to the results:

function run() {
  let blankQueryForWarmUp = "";
  let found = People.People.searchContacts({
    "query": blankQueryForWarmUp,
    "readMask": "names,addresses,emailAddresses,phoneNumbers"
  });

  Utilities.sleep(5000);

  let query = "Q12755";
  found = People.People.searchContacts({
    "query": query,
    "readMask": "names,addresses,emailAddresses,phoneNumbers"
  });

  if (found.results) {
    for (i = 0; i < found.results.length; i++) {
      let thisResult = found.results[i];
      Logger.log(`Result ${i}: ${thisResult.person.names[0].displayName}`);
    }
  } else {
    Logger.log(`No results for ${query}`);
  }
}

enter image description here

Rubén
  • 34,714
  • 9
  • 70
  • 166
MrGreggles
  • 6,113
  • 9
  • 42
  • 48

3 Answers3

1

Answer:

People API search queries only support partial string matches in contact names. The readMask values must be concatenated as a comma-separated string.

More Information:

People API Search Queries do not support the Drive syntax such as 'contains' keywords. From the documentation (emphasis my own):

query The plain-text query for the request. The query is used to match prefix phrases of the fields on a person. For example, a person with name "foo name" matches queries such as "f", "fo", "foo", "foo n", "nam", etc., but not "oo n".

The readMask can take any of the following values (taken from here), separated by commas:

  • addresses
  • ageRanges
  • biographies
  • birthdays
  • calendarUrls
  • clientData
  • coverPhotos
  • emailAddresses
  • events
  • externalIds
  • genders
  • imClients
  • interests
  • locales
  • locations
  • memberships
  • metadata
  • miscKeywords
  • names
  • nicknames
  • occupations
  • organizations
  • phoneNumbers
  • photos
  • relations
  • sipAddresses
  • skills
  • urls
  • userDefined

Code Example:

A full JavaScript request example would look like:

function run() {
  return gapi.client.people.people.searchContacts({
    "query": "Rafa Guillermo",
    "readMask": "names,emailAddresses,phoneNumbers"
  }).then(function(response) {
    console.log("Response", response)
  }, function(err) { 
    console.error(err);
  })
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54
  • Thank you very much Rafi. It's just an Appscript script attached to a Google Sheet so I've modified it to work in that context but it's not retrieving all results. I've updated the question with details. Any thoughts? – MrGreggles Sep 16 '21 at 23:22
  • Are the entries two distinct contacts or are they the same contact saved twice? – Rafa Guillermo Sep 27 '21 at 10:59
  • Hi Rafa, They are two distinct contacts sharing the same quote number (which is in the name) and address, being Owner and Tenant of a property. – MrGreggles Sep 27 '21 at 18:10
  • Truthfully I can't reproduce this. What fields in the contacts are filled? – Rafa Guillermo Sep 28 '21 at 10:43
  • Thank you sincerely Rafa for your follow up. I won't be working on this until maybe this weekend and will report back here if there are further issues identified. – MrGreggles Sep 29 '21 at 09:45
1

Add pageSize property to the searchContacts parameter. The following example uses another resource but shows the use of pageSize (it's the same for many Google API's

function run() {
  var response;
  var options = {
    pageSize:10,
    personFields: 'names'
  };
  var callback = People.People.Connections.list
  do{
    response = callback('people/me',options)
  response.connections.forEach(connection => console.log(connection.names ? connection.names[0].displayName : ''));
  options.pageToken = response.nextPageToken
  } while(options.pageToken)
}

Related

Rubén
  • 34,714
  • 9
  • 70
  • 166
1

The reason you are not seeing all the results is that the search is being done on some google cache, and so, for refreshing it, according to the documentation at: https://developers.google.com/people/api/rest/v1/people/searchContacts

You must first send a "warmup" request, wait for a couple of seconds, and after that, send your request, yes, it is strange I know, but that is what the documentation says...

IMPORTANT: Before searching, clients should send a warmup request with an empty query to update the cache. See https://developers.google.com/people/v1/contacts#search_the_users_contacts

You can also see here how exactly it is being done (see the Java tab): https://developers.google.com/people/v1/contacts#search_the_users_contacts

CORRECTION: If you are searching by phone number, just know there is a bug on Google API See this thread - searchContacts with phone number query is broken Google say the bug was fixed and verified, but it wasn't at least while I'm writing this correction.

WORKAROUND: I just put the phone number also as one of the nickname field and so the search is working since this is one of the fields being searched at

Oz Ben-David
  • 1,589
  • 1
  • 16
  • 26
  • The OP already mentions "warmup": `P.P.S. A "warmup" of the cache is recommended/required, and I'm assuming the updated script below does that okay. There's no difference to the results:` – Rubén Jan 27 '23 at 00:47