{"action":"created","issue":{"url":"https://api.github.com/repos/inonit/drf-haystack/issues/23","labels_url":"https://api.github.com/repos/inonit/drf-haystack/issues/23/labels{/name}","comments_url":"https://api.github.com/repos/inonit/drf-haystack/issues/23/comments","events_url":"https://api.github.com/repos/inonit/drf-haystack/issues/23/events","html_url":"https://github.com/inonit/drf-haystack/pull/23","id":102039897,"number":23,"title":"Fix multiple index field support","user":{"login":"jannon","id":224806,"avatar_url":"https://avatars.githubusercontent.com/u/224806?v=3","gravatar_id":"","url":"https://api.github.com/users/jannon","html_url":"https://github.com/jannon","followers_url":"https://api.github.com/users/jannon/followers","following_url":"https://api.github.com/users/jannon/following{/other_user}","gists_url":"https://api.github.com/users/jannon/gists{/gist_id}","starred_url":"https://api.github.com/users/jannon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jannon/subscriptions","organizations_url":"https://api.github.com/users/jannon/orgs","repos_url":"https://api.github.com/users/jannon/repos","events_url":"https://api.github.com/users/jannon/events{/privacy}","received_events_url":"https://api.github.com/users/jannon/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-08-20T02:00:05Z","updated_at":"2015-08-24T07:56:53Z","closed_at":"2015-08-23T18:57:45Z","pull_request":{"url":"https://api.github.com/repos/inonit/drf-haystack/pulls/23","html_url":"https://github.com/inonit/drf-haystack/pull/23","diff_url":"https://github.com/inonit/drf-haystack/pull/23.diff","patch_url":"https://github.com/inonit/drf-haystack/pull/23.patch"},"body":"Okay, this ended up being more involved than I originally thought, but here's a PR with enhanced support for using multiple indexes.  I'll describe the following major pieces below:\r\n* Automatic Multiple Index Field Handling\r\n* Ability to Use Multiple Serializers\r\n* Serializer Mixin\r\n* Miscellaneous\r\n\r\n## Automatic Multiple Index Field Handling\r\n\r\nThe original problem that needed to be solved was that if you used multiple indexes that had overlapping field names, only one field would be used.  If they happened to be different field types, that would be a big problem.\r\n\r\nThe code in this PR internally modifies the field names to associate them with a specific index.  Let's say we have the following setup:\r\n\r\n```python\r\nclass Index1(indexes.searchIndex, indexes.Indexable):\r\n    text = indexes.CharField(document=True, use_template=True)\r\n    my_field = indexes.CharField()\r\n    ...\r\n\r\nclass Index2(indexes.searchIndex, indexes.Indexable):\r\n    text = indexes.CharField(document=True, use_template=True)\r\n    my_field = indexes.IntegerField()\r\n    ...\r\n\r\nclass MySerializer(HaystackSerializer):\r\n    class Meta:\r\n        index_classes = [Index1, Index2]\r\n```\r\n\r\nInternally, the fields will be given the following names:\r\n* `_Index1__text`\r\n* `_Index2__text`\r\n* `_Index1__my_field`\r\n* `_Index2__my_field`\r\n\r\nThus, no overlap issues occur.  The field names are converted back during serialization so the handling is transparent to the user.  To make this work, the classes in the `_field_mapping` had to be replaced with proxy versions that handle the renaming\r\n\r\n## Ability to Use Multiple Serializers\r\n\r\nAs an alternative to the automatic handling above, a user may choose to specify a dictionary of Index:Serializer mappings to user a separate serializer of his or her choosing for each index.  Let's say we also have:\r\n\r\n```python\r\nclass Serializer1(serializers.Serializer):\r\n    ...\r\n\r\nclass Serializer2(serializers.Serializer):\r\n    ...\r\n\r\nclass MySerializer2(HaystackSerializer):\r\n    class Meta:\r\n        serializers = {\r\n            Index1: Serializer1,\r\n            Index2: Serializer2\r\n        }\r\n```\r\n\r\nEach result will be serialized by the appropriate serializer.  `serializers` takes precedent if `index_classes` is also specified.\r\n\r\n## Serializer Mixin\r\n\r\nA `HaystackSerializerMixin` class is provided as convenience to easily reuse existing model serializers.  This can be desireable if you want to return the same data formats from your search APIs that you do from your other APIs and have complex formats that you don't want to recreate with search indexes.  And if you don't mind the performance hit.  We might have something like:\r\n\r\n```python\r\nclass Model1Serializer(serializers.ModelSerializer):\r\n    ...\r\n\r\nclass Model2Serializer(serializers.ModelSerializer):\r\n    ...\r\n\r\nclass Model1SearchSerializer(HaystackSerializerMixin, Model1Serializer):\r\n    pass\r\n\r\nclass Model2SearchSerializer(HaystackSerializerMixin, Model2Serializer):\r\n    pass\r\n\r\nclass MySerializer3(HaystackSerializer):\r\n    class Meta:\r\n        serializers = {\r\n            Index1: Model1SearchSerializer,\r\n            Index2: Model2SearchSerializer\r\n        }\r\n```\r\n\r\n## Miscellaneous\r\n\r\nThis PR comes with updated tests and documentation, as well, including a migration and fixture for a third mock model (MockPet) in the test app.  \r\n\r\nMoving forward, I'm considering adding an option to have the serializer automatically inject a 'type' field or the like, to more readily facilitate post-processing of the results list (e.g. separating out results by type), but for the time being users can achieve this themselves by adding something to their serializers or indexes"},"comment":{"url":"https://api.github.com/repos/inonit/drf-haystack/issues/comments/134081461","html_url":"https://github.com/inonit/drf-haystack/pull/23#issuecomment-134081461","issue_url":"https://api.github.com/repos/inonit/drf-haystack/issues/23","id":134081461,"user":{"login":"jannon","id":224806,"avatar_url":"https://avatars.githubusercontent.com/u/224806?v=3","gravatar_id":"","url":"https://api.github.com/users/jannon","html_url":"https://github.com/jannon","followers_url":"https://api.github.com/users/jannon/followers","following_url":"https://api.github.com/users/jannon/following{/other_user}","gists_url":"https://api.github.com/users/jannon/gists{/gist_id}","starred_url":"https://api.github.com/users/jannon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jannon/subscriptions","organizations_url":"https://api.github.com/users/jannon/orgs","repos_url":"https://api.github.com/users/jannon/repos","events_url":"https://api.github.com/users/jannon/events{/privacy}","received_events_url":"https://api.github.com/users/jannon/received_events","type":"User","site_admin":false},"created_at":"2015-08-24T07:56:53Z","updated_at":"2015-08-24T07:56:53Z","body":"Great!  Yeah, thanks for creating the project"}}