Skip to content

Commit

Permalink
[1607] Changed group_member_save so that we can find out which items …
Browse files Browse the repository at this point in the history
…have been added/removed when saving a group. This will let us force a re-index in solr if a model.Member is changed.
  • Loading branch information
rossjones committed Feb 27, 2012
1 parent f7ca475 commit a438e11
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 29 deletions.
24 changes: 21 additions & 3 deletions ckan/lib/dictization/model_save.py
Expand Up @@ -320,24 +320,36 @@ def group_member_save(context, group_dict, member_table_name):
group_id=group.id,
).all()

entity_member = dict(((member.table_id, member.capacity), member) for member in members)
processed = {
'added': [],
'removed': []
}

entity_member = dict(((member.table_id, member.capacity), member) for member in members)
for entity_id in set(entity_member.keys()) - set(entities.keys()):
if entity_member[entity_id].state != 'deleted':
processed['removed'].append(entity_id[0])
entity_member[entity_id].state = 'deleted'
session.add(entity_member[entity_id])

for entity_id in set(entity_member.keys()) & set(entities.keys()):
if entity_member[entity_id].state != 'active':
processed['added'].append(entity_id[0])
entity_member[entity_id].state = 'active'
session.add(entity_member[entity_id])

for entity_id in set(entities.keys()) - set(entity_member.keys()):
member = Member(group=group, group_id=group.id, table_id=entity_id[0],
table_name=member_table_name[:-1],
capacity=entity_id[1])
processed['added'].append(entity_id[0])
session.add(member)

return processed


def group_dict_save(group_dict, context):
from ckan.lib.search import rebuild
import uuid

model = context["model"]
Expand All @@ -355,11 +367,18 @@ def group_dict_save(group_dict, context):

context['group'] = group

group_member_save(context, group_dict, 'packages')
pkgs_edited = group_member_save(context, group_dict, 'packages')
group_member_save(context, group_dict, 'users')
group_member_save(context, group_dict, 'groups')
group_member_save(context, group_dict, 'tags')

# We will get a list of packages that we have either added or
# removed from the group, and trigger a re-index.
package_ids = pkgs_edited['removed']
package_ids.extend( pkgs_edited['added'] )
session.flush()
map( rebuild, package_ids )

extras = group_extras_save(group_dict.get("extras", {}), context)
if extras or not allow_partial_update:
old_extras = set(group.extras.keys())
Expand All @@ -369,7 +388,6 @@ def group_dict_save(group_dict, context):
for key in new_extras:
group.extras[key] = extras[key]


return group


Expand Down
52 changes: 26 additions & 26 deletions ckan/lib/search/index.py
Expand Up @@ -16,7 +16,7 @@
PACKAGE_TYPE = "package"
KEY_CHARS = string.digits + string.letters + "_-"
SOLR_FIELDS = [TYPE_FIELD, "res_url", "text", "urls", "indexed_ts", "site_id"]
RESERVED_FIELDS = SOLR_FIELDS + ["tags", "groups", "res_description",
RESERVED_FIELDS = SOLR_FIELDS + ["tags", "groups", "res_description",
"res_format", "res_url"]
RELATIONSHIP_TYPES = PackageRelationship.types

Expand All @@ -39,55 +39,55 @@ def clear_index():
conn.close()

class SearchIndex(object):
"""
A search index handles the management of documents of a specific type in the
index, but no queries.
The default implementation maps many of the methods, so most subclasses will
only have to implement ``update_dict`` and ``remove_dict``.
"""
"""
A search index handles the management of documents of a specific type in the
index, but no queries.
The default implementation maps many of the methods, so most subclasses will
only have to implement ``update_dict`` and ``remove_dict``.
"""

def __init__(self):
pass

def insert_dict(self, data):
""" Insert new data from a dictionary. """
return self.update_dict(data)

def update_dict(self, data):
""" Update data from a dictionary. """
log.debug("NOOP Index: %s" % ",".join(data.keys()))

def remove_dict(self, data):
""" Delete an index entry uniquely identified by ``data``. """
log.debug("NOOP Delete: %s" % ",".join(data.keys()))

def clear(self):
""" Delete the complete index. """
clear_index()

def get_all_entity_ids(self):
""" Return a list of entity IDs in the index. """
raise NotImplemented

class NoopSearchIndex(SearchIndex): pass

class PackageSearchIndex(SearchIndex):
def remove_dict(self, pkg_dict):
self.delete_package(pkg_dict)

def update_dict(self, pkg_dict):
self.index_package(pkg_dict)

def index_package(self, pkg_dict):
if pkg_dict is None:
return
if pkg_dict is None:
return

if (not pkg_dict.get('state')) or ('active' not in pkg_dict.get('state')):
return self.delete_package(pkg_dict)

conn = make_connection()
index_fields = RESERVED_FIELDS + pkg_dict.keys()

# include the extras in the main namespace
extras = pkg_dict.get('extras', {})
for (key, value) in extras.items():
Expand All @@ -100,26 +100,26 @@ def index_package(self, pkg_dict):
if 'extras' in pkg_dict:
del pkg_dict['extras']

# flatten the structure for indexing:
# flatten the structure for indexing:
for resource in pkg_dict.get('resources', []):
for (okey, nkey) in [('description', 'res_description'),
('format', 'res_format'),
('url', 'res_url')]:
pkg_dict[nkey] = pkg_dict.get(nkey, []) + [resource.get(okey, u'')]
if 'resources' in pkg_dict:
del pkg_dict['resources']

# index relationships as <type>:<object>
rel_dict = {}
rel_types = list(itertools.chain(RELATIONSHIP_TYPES))
for rel in pkg_dict.get('relationships', []):
_type = rel.get('type', 'rel')
if (_type in pkg_dict.keys()) or (_type not in rel_types):
if (_type in pkg_dict.keys()) or (_type not in rel_types):
continue
rel_dict[_type] = rel_dict.get(_type, []) + [rel.get('object')]

pkg_dict.update(rel_dict)

if 'relationships' in pkg_dict:
del pkg_dict['relationships']

Expand All @@ -134,7 +134,7 @@ def index_package(self, pkg_dict):

# mark this CKAN instance as data source:
pkg_dict['site_id'] = config.get('ckan.site_id')

# add a unique index_id to avoid conflicts
import hashlib
pkg_dict['index_id'] = hashlib.md5('%s%s' % (pkg_dict['id'],config.get('ckan.site_id'))).hexdigest()
Expand All @@ -144,16 +144,16 @@ def index_package(self, pkg_dict):

assert pkg_dict, 'Plugin must return non empty package dict on index'

# send to solr:
# send to solr:
try:
conn.add_many([pkg_dict])
conn.commit(wait_flush=False, wait_searcher=False)
except Exception, e:
log.exception(e)
raise SearchIndexError(e)
finally:
conn.close()
conn.close()

log.debug("Updated index for %s" % pkg_dict.get('name'))

def delete_package(self, pkg_dict):
Expand Down

0 comments on commit a438e11

Please sign in to comment.