Answers.Body: <p>I don't know the answer about hidden smart groups but I took a swipe at the API chaining and was able to pull a contact on the demo server that met one criteria on the contact and another on the geocode on the address:</p>
  
  <p><a href="https://i.sstatic.net/wCpYD.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/wCpYD.jpg" alt="API Explorer"></a></p>
  
  <p>I don't know if that is helpful at all, but if you can get the first portion of this API call working with your custom field, it seems you should be able to chain the geocode to it.</p>
  
  <p>The code for the above comes out like this (PHP):</p>
  
  <pre><code>$result = civicrm_api3('Contact', 'get', array(
  'sequential' =&gt; 1,
  'custom_11' =&gt; 1,
  'api.Address.get' =&gt; "array( 'geo_code_1' =&gt; array('IS NOT NULL' =&gt; 1), )",
  ));
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-08-13T02:29:50.240Z
Answers.LastActivityDate: 2015-08-13T02:29:50.240Z
Answers.UserDisplayName: Laryn
Body: <p>For the Electoral API extension, I want to write a scheduled job to look up legislative data for everyone who a) has a geocode, and b) doesn't already have legislative data (which is stored in a multi-record custom field).  I need this to be scalable.</p>
  
  <p>So I could look up every contact without legislative data, then check those contacts for geocodes, or vice versa.  Either way, I'm checking a huge number of contacts for data.  Is there a better way?  Maybe using API chaining?</p>
  
  <p>Is it possible to create a smart group that's hidden from the UI that meets these criteria, then use that as the basis for my scheduled job?  That seems like the best option.</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2015-08-13T02:34:33.297Z
Comments.Text: A key requirement of scalability is to have proper indexes. Make sure you have an index on civicrm_address.geo_code_1, and on the contact ID field of the custom table as well. If it's still too slow once indexes are in place, it may require skipping the API and writing the optimized SQL directly. If you get to that point, I'm happy to review the query and make optimization suggestions.
Comments.UserDisplayName: Nicholai
Tags: <api><developer><smartgroups><chaining>
Title: How can I find contacts based on both custom data and address via the API?
ThreadText: # How can I find contacts based on both custom data and address via the API?
  
  (Asked by: username_0 on 2015-08-05)
  
  For the Electoral API extension, I want to write a scheduled job to look up legislative data for everyone who a) has a geocode, and b) doesn't already have legislative data (which is stored in a multi-record custom field). I need this to be scalable.
  
  So I could look up every contact without legislative data, then check those contacts for geocodes, or vice versa. Either way, I'm checking a huge number of contacts for data. Is there a better way? Maybe using API chaining?
  
  Is it possible to create a smart group that's hidden from the UI that meets these criteria, then use that as the basis for my scheduled job? That seems like the best option.
  
  **Tags:** api, developer, smartgroups, chaining
  
  > **Comments:**
  > **username_1**: A key requirement of scalability is to have proper indexes. Make sure you have an index on civicrm_address.geo_code_1, and on the contact ID field of the custom table as well. If it's still too slow once indexes are in place, it may require skipping the API and writing the optimized SQL directly. If you get to that point, I'm happy to review the query and make optimization suggestions.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2015-08-13. Score: 1
  
  I don't know the answer about hidden smart groups but I took a swipe at the API chaining and was able to pull a contact on the demo server that met one criteria on the contact and another on the geocode on the address:
  
  I don't know if that is helpful at all, but if you can get the first portion of this API call working with your custom field, it seems you should be able to chain the geocode to it.
  The code for the above comes out like this (PHP):
  $result = civicrm_api3('Contact', 'get', array(
  'sequential' => 1,
  'custom_11' => 1,
  'api.Address.get' => "array( 'geo_code_1' => array('IS NOT NULL' => 1), )",
  ));
  
  
  ---
  
  