@@ -321,7 +321,7 @@ def _gen_index_name(self, keys):
321321 """
322322 return u"_" .join ([u"%s_%s" % item for item in keys ])
323323
324- def create_index (self , key_or_list , direction = None , unique = False ):
324+ def create_index (self , key_or_list , direction = None , unique = False , ttl = 300 ):
325325 """Creates an index on this collection.
326326
327327 Takes either a single key and a direction, or a list of (key, direction)
@@ -331,27 +331,76 @@ def create_index(self, key_or_list, direction=None, unique=False):
331331
332332 :Parameters:
333333 - `key_or_list`: a single key or a list of (key, direction) pairs
334- specifying the index to ensure
334+ specifying the index to create
335335 - `direction` (optional): must be included if key_or_list is a single
336336 key, otherwise must be None
337337 - `unique` (optional): should this index guarantee uniqueness?
338+ - `ttl` (optional): time window (in seconds) during which this index
339+ will be recognized by subsequent calls to `ensure_index` - see
340+ documentation for `ensure_index` for details
338341 """
339342 to_save = SON ()
340343 keys = pymongo ._index_list (key_or_list , direction )
341- to_save ["name" ] = self ._gen_index_name (keys )
344+ name = self ._gen_index_name (keys )
345+ to_save ["name" ] = name
342346 to_save ["ns" ] = self .full_name ()
343347 to_save ["key" ] = pymongo ._index_document (keys )
344348 to_save ["unique" ] = unique
345349
346- self .__database .system .indexes .save (to_save , False )
350+ self .database ().connection ()._cache_index (self .__database .name (),
351+ self .name (),
352+ name , ttl )
353+
354+ self .database ().system .indexes .save (to_save , False )
347355 return to_save ["name" ]
348356
357+ def ensure_index (self , key_or_list , direction = None , unique = False , ttl = 300 ):
358+ """Ensures that an index exists on this collection.
359+
360+ Takes either a single key and a direction, or a list of (key, direction)
361+ pairs. The key(s) must be an instance of (str, unicode), and the
362+ direction(s) must be one of (`pymongo.ASCENDING`, `pymongo.DESCENDING`).
363+
364+ Unlike `create_index`, which attempts to create an index
365+ unconditionally, `ensure_index` takes advantage of some caching within
366+ the driver such that it only attempts to create indexes that might
367+ not already exist. When an index is created (or ensured) by PyMongo
368+ it is "remembered" for `ttl` seconds. Repeated calls to `ensure_index`
369+ within that time limit will be lightweight - they will not attempt to
370+ actually create the index.
371+
372+ Care must be taken when the database is being accessed through multiple
373+ connections at once. If an index is created using PyMongo and then
374+ deleted using another connection any call to `ensure_index` within the
375+ cache window will fail to re-create the missing index.
376+
377+ Returns the name of the created index if an index is actually created.
378+ Returns None if the index already exists.
379+
380+ :Parameters:
381+ - `key_or_list`: a single key or a list of (key, direction) pairs
382+ specifying the index to ensure
383+ - `direction` (optional): must be included if key_or_list is a single
384+ key, otherwise must be None
385+ - `unique` (optional): should this index guarantee uniqueness?
386+ - `ttl` (optional): time window (in seconds) during which this index
387+ will be recognized by subsequent calls to `ensure_index`
388+ """
389+ keys = pymongo ._index_list (key_or_list , direction )
390+ name = self ._gen_index_name (keys )
391+ if self .database ().connection ()._cache_index (self .__database .name (),
392+ self .name (),
393+ name , ttl ):
394+ return self .create_index (key_or_list , direction , unique , ttl )
395+ return None
396+
349397 def drop_indexes (self ):
350398 """Drops all indexes on this collection.
351399
352400 Can be used on non-existant collections or collections with no indexes.
353401 Raises OperationFailure on an error.
354402 """
403+ self .database ().connection ()._purge_index (self .database ().name (), self .name ())
355404 self .drop_index (u"*" )
356405
357406 def drop_index (self , index_or_name ):
@@ -373,6 +422,7 @@ def drop_index(self, index_or_name):
373422 if not isinstance (name , types .StringTypes ):
374423 raise TypeError ("index_or_name must be an index name or list" )
375424
425+ self .database ().connection ()._purge_index (self .database ().name (), self .name (), name )
376426 self .__database ._command (SON ([("deleteIndexes" ,
377427 self .__collection_name ),
378428 ("index" , name )]),
0 commit comments