0
# Query Autocompletion
1
2
Query autocompletion and suggestion functionality for building intelligent search interfaces with support for job titles, companies, and location-based suggestions. The completion service provides real-time query suggestions to improve user search experience and help users discover relevant job opportunities.
3
4
## Capabilities
5
6
### Query Completion
7
8
Provides intelligent autocompletion suggestions for job search queries based on job titles, company names, skills, and locations within the tenant's job dataset.
9
10
```python { .api }
11
def complete_query(self, tenant: str, query: str, page_size: int = None,
12
language_codes: List[str] = None, company: str = None,
13
scope: CompletionScope = None, type_: CompletionType = None) -> CompleteQueryResponse:
14
"""
15
Returns autocomplete suggestions for job search queries.
16
17
Parameters:
18
- tenant (str): Tenant resource name for scoped suggestions
19
- query (str): Partial query string to complete (required, max 255 chars)
20
- page_size (int): Maximum number of suggestions to return (max 100, default 10)
21
- language_codes (List[str]): Preferred languages for suggestions (ISO 639-1 codes)
22
- company (str): Company resource name to scope suggestions
23
- scope (CompletionScope): Scope of completion suggestions
24
- type_ (CompletionType): Type of completion to perform
25
26
Returns:
27
CompleteQueryResponse: Completion suggestions with metadata
28
29
Raises:
30
- InvalidArgument: Invalid query string or parameters
31
- PermissionDenied: Insufficient permissions for completion requests
32
"""
33
```
34
35
**Usage Example:**
36
37
```python
38
from google.cloud.talent import CompletionClient, CompletionScope, CompletionType
39
40
client = CompletionClient()
41
42
# Basic query completion
43
response = client.complete_query(
44
tenant="projects/my-project/tenants/my-tenant",
45
query="software eng",
46
page_size=10
47
)
48
49
for completion in response.completion_results:
50
print(f"Suggestion: {completion.suggestion}")
51
print(f"Type: {completion.type_}")
52
```
53
54
## Completion Configuration
55
56
### Completion Scope
57
58
Controls the scope of suggestions to provide targeted autocompletion.
59
60
```python { .api }
61
class CompletionScope(Enum):
62
"""Scope options for completion suggestions."""
63
COMPLETION_SCOPE_UNSPECIFIED = 0
64
TENANT = 1 # Suggestions from tenant's job data
65
PUBLIC = 2 # Suggestions from public job market data
66
```
67
68
### Completion Type
69
70
Specifies the type of completion to perform for different use cases.
71
72
```python { .api }
73
class CompletionType(Enum):
74
"""Types of completion suggestions."""
75
COMPLETION_TYPE_UNSPECIFIED = 0
76
JOB_TITLE = 1 # Job title completions
77
COMPANY_NAME = 2 # Company name completions
78
COMBINED = 3 # Combined job title and company suggestions
79
```
80
81
**Usage Examples:**
82
83
```python
84
# Job title specific completions
85
title_response = client.complete_query(
86
tenant="projects/my-project/tenants/my-tenant",
87
query="data sci",
88
type_=CompletionType.JOB_TITLE,
89
page_size=15
90
)
91
92
# Company name completions
93
company_response = client.complete_query(
94
tenant="projects/my-project/tenants/my-tenant",
95
query="goog",
96
type_=CompletionType.COMPANY_NAME,
97
page_size=10
98
)
99
100
# Combined suggestions for general search
101
combined_response = client.complete_query(
102
tenant="projects/my-project/tenants/my-tenant",
103
query="python",
104
type_=CompletionType.COMBINED,
105
scope=CompletionScope.TENANT,
106
page_size=20
107
)
108
```
109
110
### Language-Specific Completions
111
112
Request completions in specific languages for internationalized applications.
113
114
```python
115
# Multi-language completion support
116
multilingual_response = client.complete_query(
117
tenant="projects/my-project/tenants/my-tenant",
118
query="desarrollador", # Spanish for "developer"
119
language_codes=["es", "en"], # Spanish and English
120
page_size=10
121
)
122
123
# English-only completions
124
english_response = client.complete_query(
125
tenant="projects/my-project/tenants/my-tenant",
126
query="engineer",
127
language_codes=["en"],
128
page_size=15
129
)
130
```
131
132
### Company-Scoped Completions
133
134
Scope completions to specific companies for targeted job searches.
135
136
```python
137
# Completions scoped to specific company
138
company_scoped_response = client.complete_query(
139
tenant="projects/my-project/tenants/my-tenant",
140
query="software",
141
company="projects/my-project/tenants/my-tenant/companies/google",
142
page_size=10
143
)
144
145
for completion in company_scoped_response.completion_results:
146
print(f"Job at Google: {completion.suggestion}")
147
```
148
149
## Response Structure
150
151
### Completion Response
152
153
```python { .api }
154
class CompleteQueryResponse:
155
"""Response containing completion suggestions and metadata."""
156
completion_results: List[CompletionResult] = None # List of suggestions
157
metadata: ResponseMetadata = None # Response metadata
158
159
class CompletionResult:
160
"""Individual completion suggestion with metadata."""
161
suggestion: str = None # Completed query suggestion
162
type_: CompletionType = None # Type of suggestion
163
image_uri: str = None # Associated image (for company suggestions)
164
```
165
166
**Response Processing:**
167
168
```python
169
response = client.complete_query(
170
tenant="projects/my-project/tenants/my-tenant",
171
query="java dev",
172
type_=CompletionType.COMBINED
173
)
174
175
print(f"Found {len(response.completion_results)} suggestions:")
176
177
for result in response.completion_results:
178
print(f" {result.suggestion} ({result.type_})")
179
180
if result.image_uri:
181
print(f" Logo: {result.image_uri}")
182
```
183
184
## Request and Response Types
185
186
### Completion Service Requests
187
188
```python { .api }
189
class CompleteQueryRequest:
190
tenant: str = None # Tenant resource name (required)
191
query: str = None # Partial query to complete (required, max 255 chars)
192
language_codes: List[str] = None # Preferred languages (ISO 639-1)
193
page_size: int = None # Max suggestions to return (max 100, default 10)
194
company: str = None # Company resource name for scoping
195
scope: CompletionScope = None # Completion scope
196
type_: CompletionType = None # Completion type
197
```
198
199
## Integration Patterns
200
201
### Real-Time Search Interface
202
203
Implement debounced autocompletion for responsive search interfaces.
204
205
```python
206
import asyncio
207
import time
208
from typing import List, Optional
209
210
class SearchAutocompletion:
211
def __init__(self, tenant_name: str, debounce_ms: int = 300):
212
self.tenant_name = tenant_name
213
self.client = CompletionClient()
214
self.debounce_ms = debounce_ms
215
self.last_query_time = 0
216
self.current_task = None
217
218
async def get_suggestions(self, query: str, max_suggestions: int = 10) -> List[str]:
219
"""Get suggestions with debouncing for real-time search."""
220
if len(query.strip()) < 2:
221
return []
222
223
# Cancel previous request if still pending
224
if self.current_task and not self.current_task.done():
225
self.current_task.cancel()
226
227
# Debounce rapid queries
228
self.last_query_time = time.time()
229
await asyncio.sleep(self.debounce_ms / 1000.0)
230
231
# Check if a newer query was made during debounce period
232
if time.time() - self.last_query_time < (self.debounce_ms / 1000.0):
233
return []
234
235
# Make completion request
236
self.current_task = asyncio.create_task(
237
self._fetch_completions(query, max_suggestions)
238
)
239
240
try:
241
return await self.current_task
242
except asyncio.CancelledError:
243
return []
244
245
async def _fetch_completions(self, query: str, max_suggestions: int) -> List[str]:
246
"""Fetch completions from API."""
247
try:
248
response = self.client.complete_query(
249
tenant=self.tenant_name,
250
query=query,
251
type_=CompletionType.COMBINED,
252
page_size=max_suggestions
253
)
254
255
return [result.suggestion for result in response.completion_results]
256
257
except Exception as e:
258
print(f"Completion request failed: {e}")
259
return []
260
261
# Usage in web application
262
autocomplete = SearchAutocompletion("projects/my-project/tenants/my-tenant")
263
264
# In request handler
265
async def handle_autocomplete_request(query: str):
266
suggestions = await autocomplete.get_suggestions(query)
267
return {"suggestions": suggestions}
268
```
269
270
### Cached Completion Service
271
272
Implement caching for frequently requested completions to improve performance.
273
274
```python
275
import time
276
from typing import Dict, Tuple, List
277
from dataclasses import dataclass
278
279
@dataclass
280
class CachedCompletion:
281
suggestions: List[str]
282
timestamp: float
283
ttl_seconds: int = 300 # 5 minutes default TTL
284
285
class CompletionCache:
286
def __init__(self, tenant_name: str, cache_ttl: int = 300):
287
self.tenant_name = tenant_name
288
self.client = CompletionClient()
289
self.cache: Dict[str, CachedCompletion] = {}
290
self.default_ttl = cache_ttl
291
292
def get_completions(self, query: str, max_suggestions: int = 10) -> List[str]:
293
"""Get completions with caching."""
294
cache_key = f"{query.lower()}:{max_suggestions}"
295
296
# Check cache first
297
if cache_key in self.cache:
298
cached = self.cache[cache_key]
299
if time.time() - cached.timestamp < cached.ttl_seconds:
300
return cached.suggestions
301
else:
302
del self.cache[cache_key] # Remove expired entry
303
304
# Fetch from API
305
try:
306
response = self.client.complete_query(
307
tenant=self.tenant_name,
308
query=query,
309
type_=CompletionType.COMBINED,
310
page_size=max_suggestions
311
)
312
313
suggestions = [result.suggestion for result in response.completion_results]
314
315
# Cache the results
316
self.cache[cache_key] = CachedCompletion(
317
suggestions=suggestions,
318
timestamp=time.time(),
319
ttl_seconds=self.default_ttl
320
)
321
322
return suggestions
323
324
except Exception as e:
325
print(f"Completion request failed: {e}")
326
return []
327
328
def clear_cache(self):
329
"""Clear all cached completions."""
330
self.cache.clear()
331
332
def clear_expired(self):
333
"""Remove expired cache entries."""
334
current_time = time.time()
335
expired_keys = [
336
key for key, cached in self.cache.items()
337
if current_time - cached.timestamp >= cached.ttl_seconds
338
]
339
340
for key in expired_keys:
341
del self.cache[key]
342
343
# Usage
344
completion_cache = CompletionCache("projects/my-project/tenants/my-tenant")
345
346
def get_search_suggestions(query: str) -> List[str]:
347
return completion_cache.get_completions(query, max_suggestions=15)
348
```
349
350
### Frontend Integration
351
352
JavaScript/TypeScript integration for web applications.
353
354
```javascript
355
class TalentAutocompletion {
356
constructor(tenantPath, apiEndpoint) {
357
this.tenantPath = tenantPath;
358
this.apiEndpoint = apiEndpoint;
359
this.debounceTimer = null;
360
this.currentController = null;
361
}
362
363
async getSuggestions(query, options = {}) {
364
// Clear previous debounce timer
365
if (this.debounceTimer) {
366
clearTimeout(this.debounceTimer);
367
}
368
369
// Cancel previous request
370
if (this.currentController) {
371
this.currentController.abort();
372
}
373
374
return new Promise((resolve, reject) => {
375
this.debounceTimer = setTimeout(async () => {
376
try {
377
this.currentController = new AbortController();
378
379
const params = new URLSearchParams({
380
tenant: this.tenantPath,
381
query: query,
382
page_size: options.maxSuggestions || 10,
383
type: options.type || 'COMBINED'
384
});
385
386
if (options.languageCodes) {
387
params.append('language_codes', options.languageCodes.join(','));
388
}
389
390
const response = await fetch(
391
`${this.apiEndpoint}/completion?${params}`,
392
{
393
signal: this.currentController.signal,
394
headers: {
395
'Authorization': `Bearer ${await this.getAuthToken()}`
396
}
397
}
398
);
399
400
if (!response.ok) {
401
throw new Error(`Completion request failed: ${response.status}`);
402
}
403
404
const data = await response.json();
405
resolve(data.completion_results || []);
406
407
} catch (error) {
408
if (error.name !== 'AbortError') {
409
reject(error);
410
}
411
}
412
}, options.debounceMs || 300);
413
});
414
}
415
416
async getAuthToken() {
417
// Implement your authentication token retrieval
418
return localStorage.getItem('auth_token');
419
}
420
}
421
422
// Usage in React component
423
const useJobSearchAutocompletion = (tenantPath) => {
424
const [suggestions, setSuggestions] = useState([]);
425
const [loading, setLoading] = useState(false);
426
const autocompletion = useRef(
427
new TalentAutocompletion(tenantPath, '/api/talent')
428
).current;
429
430
const getSuggestions = useCallback(async (query) => {
431
if (query.length < 2) {
432
setSuggestions([]);
433
return;
434
}
435
436
setLoading(true);
437
try {
438
const results = await autocompletion.getSuggestions(query, {
439
maxSuggestions: 10,
440
type: 'COMBINED'
441
});
442
setSuggestions(results.map(r => r.suggestion));
443
} catch (error) {
444
console.error('Autocompletion failed:', error);
445
setSuggestions([]);
446
} finally {
447
setLoading(false);
448
}
449
}, [autocompletion]);
450
451
return { suggestions, loading, getSuggestions };
452
};
453
```
454
455
## Error Handling
456
457
Completion operations can raise several types of exceptions:
458
459
```python
460
from google.api_core import exceptions
461
462
def safe_get_completions(client: CompletionClient, tenant: str, query: str) -> List[str]:
463
"""Safely get completions with comprehensive error handling."""
464
try:
465
response = client.complete_query(tenant=tenant, query=query)
466
return [result.suggestion for result in response.completion_results]
467
468
except exceptions.InvalidArgument as e:
469
print(f"Invalid completion query: {e}")
470
return [] # Return empty list for invalid queries
471
472
except exceptions.PermissionDenied as e:
473
print(f"Completion access denied: {e}")
474
return [] # Return empty list if no permission
475
476
except exceptions.ResourceExhausted as e:
477
print(f"Completion quota exceeded: {e}")
478
return [] # Return empty list if quota exceeded
479
480
except exceptions.DeadlineExceeded as e:
481
print(f"Completion request timeout: {e}")
482
return [] # Return empty list on timeout
483
484
except Exception as e:
485
print(f"Unexpected completion error: {e}")
486
return [] # Never break user experience for completion failures
487
```
488
489
Common error scenarios:
490
- **InvalidArgument**: Empty query, query too long, invalid parameters
491
- **PermissionDenied**: Insufficient IAM permissions for completion requests
492
- **ResourceExhausted**: Completion API quota limits exceeded
493
- **DeadlineExceeded**: Completion request timeout
494
495
## Best Practices
496
497
1. **Query Length**: Only request completions for queries with 2+ characters to avoid noise
498
2. **Debouncing**: Implement debouncing (200-300ms) to avoid excessive API requests during typing
499
3. **Caching**: Cache frequent completions locally to improve performance and reduce API calls
500
4. **Error Handling**: Gracefully handle failures without breaking the search experience
501
5. **Performance**: Limit suggestion counts (5-15) for optimal user experience
502
6. **Cancellation**: Cancel previous requests when new queries are made
503
7. **Accessibility**: Ensure autocompletion interfaces are keyboard and screen reader accessible
504
8. **Analytics**: Track completion usage to optimize suggestion quality and performance
505
506
## Performance Optimization
507
508
### Request Optimization
509
510
```python
511
# Optimize completion requests for performance
512
def optimized_completion_request(query: str) -> CompleteQueryRequest:
513
return CompleteQueryRequest(
514
tenant="projects/my-project/tenants/my-tenant",
515
query=query,
516
page_size=8, # Smaller page size for faster response
517
type_=CompletionType.COMBINED, # Most useful for general search
518
scope=CompletionScope.TENANT # Faster than public scope
519
)
520
```
521
522
### Monitoring and Analytics
523
524
```python
525
import time
526
from collections import defaultdict
527
528
class CompletionAnalytics:
529
def __init__(self):
530
self.request_counts = defaultdict(int)
531
self.response_times = []
532
self.error_counts = defaultdict(int)
533
534
def track_request(self, query: str, response_time: float, success: bool, error_type: str = None):
535
"""Track completion request metrics."""
536
self.request_counts[query] += 1
537
self.response_times.append(response_time)
538
539
if not success and error_type:
540
self.error_counts[error_type] += 1
541
542
def get_metrics(self):
543
"""Get completion performance metrics."""
544
if not self.response_times:
545
return {}
546
547
return {
548
'total_requests': sum(self.request_counts.values()),
549
'unique_queries': len(self.request_counts),
550
'avg_response_time': sum(self.response_times) / len(self.response_times),
551
'error_rate': sum(self.error_counts.values()) / sum(self.request_counts.values()),
552
'most_common_queries': sorted(
553
self.request_counts.items(),
554
key=lambda x: x[1],
555
reverse=True
556
)[:10]
557
}
558
```