Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

first commit of solr branch, switching to haystack+Solr backend inste…

…ad of just postgres search
  • Loading branch information...
commit 436191587be7ba13ddefcc955f082b90716c2d71 1 parent 0c0494e
Charles DeTar authored
View
1  afg/fixtures/initial_data.json
@@ -0,0 +1 @@
+[{"pk": 22, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 8}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "add_diaryentry", "name": "Can add diary entry", "content_type": 9}}, {"pk": 26, "model": "auth.permission", "fields": {"codename": "change_diaryentry", "name": "Can change diary entry", "content_type": 9}}, {"pk": 27, "model": "auth.permission", "fields": {"codename": "delete_diaryentry", "name": "Can delete diary entry", "content_type": 9}}, {"pk": 28, "model": "auth.permission", "fields": {"codename": "add_phrase", "name": "Can add phrase", "content_type": 10}}, {"pk": 29, "model": "auth.permission", "fields": {"codename": "change_phrase", "name": "Can change phrase", "content_type": 10}}, {"pk": 30, "model": "auth.permission", "fields": {"codename": "delete_phrase", "name": "Can delete phrase", "content_type": 10}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 2}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 2}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 2}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_message", "name": "Can add message", "content_type": 4}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_message", "name": "Can change message", "content_type": 4}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_message", "name": "Can delete message", "content_type": 4}}, {"pk": 1, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 1}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 1}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 1}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 3}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 3}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 3}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 5}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 6}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 7}}, {"pk": 1, "model": "auth.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": true, "last_login": "2010-09-07 16:13:29", "groups": [], "user_permissions": [], "password": "sha1$4ff10$21ae972ee9dbaaae152d861e77d2c2570f284511", "email": "admin@admin.com", "date_joined": "2010-09-07 16:13:29"}}]
View
76 afg/management/commands/import_wikileaks.py
@@ -1,11 +1,14 @@
+import re
import csv
import datetime
+import itertools
from collections import defaultdict
from django.core.management.base import BaseCommand
from django.db import connection
+from django.contrib.gis.geos import GEOSGeometry
-from afg import models
+from afg.models import DiaryEntry, Phrase
fields = ["report_key", # 0
"date", # 1
@@ -39,57 +42,60 @@
"affiliation", # 29
"dcolor", # 30
"classification", # 31
-]
+]
+def clean_summary(text):
+ # Fix ampersand mess
+ while text.find("&") != -1:
+ text = text.replace("&", "&")
+ text = re.sub('&(?!(#[a-z\d]+|\w+);)/gi', "&", text)
+
+ # Linebreaks
+ text = text.replace("\n", "<br />")
+ return text
class Command(BaseCommand):
args = '<csv_file>'
- help = """Import the wikileaks Afghan war diaries csv file."""
+ help = """Import the wikileaks Afghan War Diary CSV file."""
def handle(self, *args, **kwargs):
if len(args) < 1:
- print """Requires one argument: the path to the wikileaks Afghan war
-diaries csv file."""
+ print """Requires one argument: the path to the wikileaks Afghan War Diary CSV file. It can be downloaded here:
+
+http://wikileaks.org/wiki/Afghan_War_Diary,_2004-2010
+
+"""
return
with open(args[0]) as fh:
reader = csv.reader(fh)
- for row in reader:
- # Create model
+ for c, row in enumerate(itertools.islice(reader, 0, 1000)):
+ print c
for i in range(13, 22):
row[i] = int(row[i] or 0)
-
- entry = models.DiaryEntry.objects.create(
- **dict(zip(fields, row))
- )
-
- summary = row[6]
- words = summary.upper().split()
+ kwargs = dict(zip(fields, row))
+ lon, lat = kwargs.pop('longitude'), kwargs.pop('latitude')
+ if lon and lat:
+ kwargs['point'] = "POINT(%s %s)" % (lon, lat)
+ kwargs['summary'] = clean_summary(kwargs['summary'])
+ kwargs['total_casualties'] = (kwargs['friendly_wia'] + kwargs['friendly_kia'] +
+ kwargs['host_nation_wia'] + kwargs['host_nation_kia'] +
+ kwargs['civilian_wia'] + kwargs['civilian_kia'] +
+ kwargs['enemy_wia'] + kwargs['enemy_kia'])
+ entry = DiaryEntry.objects.get_or_create(**kwargs)[0]
+ # Get words for phrases
+ summary = re.sub(r'<[^>]*?>', '', kwargs['summary'])
+ summary = re.sub(r'&[^;\s]+;', ' ', summary)
+ summary = re.sub(r'[^A-Z ]', ' ', summary.upper())
+ summary = re.sub(r'\s+', ' ', summary).strip()
+ words = summary.split(' ')
for i in range(3, 1, -1):
for j in range(i, len(words)):
- phrase = models.Phrase.objects.get_or_create(
- phrase=" ".join(words[j-i:j])[:255]
- )[0]
+ phrase = Phrase.objects.get_or_create(phrase=" ".join(words[j-i:j])[:255])[0]
entry.phrase_set.add(phrase)
-
- # denormalize entry counts.
+
+ # dennormalize entry counts
cursor = connection.cursor()
cursor.execute("""
UPDATE afg_phrase SET entry_count = (SELECT COUNT(pe.*) FROM afg_phrase_entries pe WHERE pe.phrase_id = afg_phrase.id)
""")
-
- # Postgresql full text search index
- cursor.execute("""
-BEGIN;
-ALTER TABLE afg_diaryentry ADD COLUMN summary_tsv tsvector;
-CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON afg_diaryentry
- FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(summary_tsv, 'pg_catalog.english', summary);
-CREATE INDEX summary_tsv_index ON afg_diaryentry USING gin(summary_tsv);
-UPDATE afg_diaryentry SET summary_tsv=to_tsvector(summary);
-COMMIT;
- """)
-
- # denormalize total_casualties
- cusror.execute("""
-UPDATE afg_diaryentry SET total_casualties = civilian_kia + civilian_wia + friendly_kia + friendly_wia + host_nation_kia + host_nation_wia + enemy_kia + enemy_wia;
-""")
View
77 afg/models.py
@@ -1,44 +1,44 @@
-from django.db import models
-
-# Create your models here.
+from django.contrib.gis.db import models
+# No DB indexes because we're kicking all that to SOLR.
class DiaryEntry(models.Model):
- report_key = models.CharField(max_length=255, db_index=True, unique=True)
- date = models.DateTimeField(db_index=True)
+ report_key = models.CharField(max_length=255, unique=True)
+ date = models.DateTimeField()
type = models.CharField(max_length=255)
- category = models.CharField(max_length=255, db_index=True)
- tracking_number = models.CharField(max_length=255, db_index=True)
- title = models.TextField(db_index=True)
- # Will get a tsvector full-text-search index
+ category = models.CharField(max_length=255)
+ tracking_number = models.CharField(max_length=255)
+ title = models.TextField()
summary = models.TextField()
- region = models.CharField(max_length=255, db_index=True)
- attack_on = models.CharField(max_length=255, db_index=True)
+ region = models.CharField(max_length=255)
+ attack_on = models.CharField(max_length=255)
complex_attack = models.BooleanField()
- reporting_unit = models.CharField(max_length=255, db_index=True)
- unit_name = models.CharField(max_length=255, db_index=True)
- type_of_unit = models.CharField(max_length=255, db_index=True)
- friendly_wia = models.IntegerField(db_index=True)
- friendly_kia = models.IntegerField(db_index=True)
- host_nation_wia = models.IntegerField(db_index=True)
- host_nation_kia = models.IntegerField(db_index=True)
- civilian_wia = models.IntegerField(db_index=True)
- civilian_kia = models.IntegerField(db_index=True)
- enemy_wia = models.IntegerField(db_index=True)
- enemy_kia = models.IntegerField(db_index=True)
- enemy_detained = models.IntegerField(db_index=True)
- mgrs = models.CharField(max_length=255, db_index=True)
- latitude = models.CharField(max_length=255, db_index=True)
- longitude = models.CharField(max_length=255, db_index=True)
- originator_group = models.CharField(max_length=255, db_index=True)
- updated_by_group = models.CharField(max_length=255, db_index=True)
- ccir = models.CharField(max_length=255, db_index=True)
- sigact = models.CharField(max_length=255, db_index=True)
- affiliation = models.CharField(max_length=255, db_index=True)
- dcolor = models.CharField(max_length=255, db_index=True)
- classification = models.CharField(max_length=255, db_index=True)
+ reporting_unit = models.CharField(max_length=255)
+ unit_name = models.CharField(max_length=255)
+ type_of_unit = models.CharField(max_length=255)
+ friendly_wia = models.IntegerField()
+ friendly_kia = models.IntegerField()
+ host_nation_wia = models.IntegerField()
+ host_nation_kia = models.IntegerField()
+ civilian_wia = models.IntegerField()
+ civilian_kia = models.IntegerField()
+ enemy_wia = models.IntegerField()
+ enemy_kia = models.IntegerField()
+ enemy_detained = models.IntegerField()
+ mgrs = models.CharField(max_length=255)
+ originator_group = models.CharField(max_length=255)
+ updated_by_group = models.CharField(max_length=255)
+ ccir = models.CharField(max_length=255)
+ sigact = models.CharField(max_length=255)
+ affiliation = models.CharField(max_length=255)
+ dcolor = models.CharField(max_length=255)
+ classification = models.CharField(max_length=255)
+ # GIS point
+ point = models.PointField(blank=True, null=True)
# denormalization for sorting
- total_casualties = models.IntegerField(default=0, db_index=True)
+ total_casualties = models.IntegerField(default=0)
+
+ objects = models.GeoManager()
def __unicode__(self):
return self.title
@@ -50,9 +50,7 @@ def to_dict(self):
return obj
class Meta:
- ordering = ['-civilian_kia', '-civilian_wia', '-host_nation_kia',
- '-host_nation_wia', '-friendly_kia', '-friendly_wia',
- 'date', 'title']
+ ordering = ['-total_casualties']
verbose_name_plural = 'Diary entries'
def casualty_summary(self):
@@ -67,12 +65,13 @@ def casualty_summary(self):
if w:
counts.append("%i wounded" % w)
parts.append("%s: %s" % (attr.title().replace("_", " "), ", ".join(counts)))
- return "; ".join(parts)
+ return "; ".join(parts)
class Phrase(models.Model):
phrase = models.CharField(max_length=255, unique=True, db_index=True)
entries = models.ManyToManyField(DiaryEntry)
- # denormalization for performance:
+
+ # denormalization for performance
entry_count = models.IntegerField(default=0, db_index=True)
def __unicode__(self):
View
46 afg/search_indexes.py
@@ -0,0 +1,46 @@
+import datetime
+from haystack import indexes
+from haystack import site
+from afg.models import DiaryEntry
+
+class DiaryEntryIndex(indexes.SearchIndex):
+ text = indexes.CharField(document=True, use_template=True)
+ report_key = indexes.CharField(model_attr='report_key')
+ date = indexes.DateTimeField(model_attr='date', faceted=True)
+ type_ = indexes.CharField(model_attr='type', faceted=True)
+ category = indexes.CharField(model_attr='category', faceted=True)
+ tracking_number = indexes.CharField(model_attr='tracking_number')
+ title = indexes.CharField(model_attr='title')
+ summary = indexes.CharField(model_attr='summary')
+ region = indexes.CharField(model_attr='region', faceted=True)
+ attack_on = indexes.CharField(model_attr='attack_on', faceted=True)
+ complex_attack = indexes.BooleanField(model_attr='complex_attack', faceted=True)
+ reporting_unit = indexes.CharField(model_attr='reporting_unit', faceted=True)
+ unit_name = indexes.CharField(model_attr='unit_name', faceted=True)
+ type_of_unit = indexes.CharField(model_attr='type_of_unit', faceted=True)
+ friendly_wia = indexes.IntegerField(model_attr='friendly_wia', faceted=True)
+ friendly_kia = indexes.IntegerField(model_attr='friendly_kia', faceted=True)
+ host_nation_wia = indexes.IntegerField(model_attr='host_nation_wia', faceted=True)
+ host_nation_kia = indexes.IntegerField(model_attr='host_nation_kia', faceted=True)
+ civilian_wia = indexes.IntegerField(model_attr='civilian_wia', faceted=True)
+ civilian_kia = indexes.IntegerField(model_attr='civilian_kia', faceted=True)
+ enemy_wia = indexes.IntegerField(model_attr='enemy_wia', faceted=True)
+ enemy_kia = indexes.IntegerField(model_attr='enemy_kia', faceted=True)
+ enemy_detained = indexes.IntegerField(model_attr='enemy_detained', faceted=True)
+ mgrs = indexes.CharField(model_attr='mgrs', faceted=True)
+ originator_group = indexes.CharField(model_attr='originator_group', faceted=True)
+ updated_by_group = indexes.CharField(model_attr='updated_by_group', faceted=True)
+ ccir = indexes.CharField(model_attr='ccir', faceted=True)
+ sigact = indexes.CharField(model_attr='sigact', faceted=True)
+ affiliation = indexes.CharField(model_attr='affiliation', faceted=True)
+ dcolor = indexes.CharField(model_attr='dcolor', faceted=True)
+ classification = indexes.CharField(model_attr='classification', faceted=True)
+ point = indexes.CharField(model_attr='point', null=True)
+
+ def get_queryset(self):
+ return DiaryEntry.objects.all()
+
+site.register(DiaryEntry, DiaryEntryIndex)
+
+
+
View
2  afg/templates/search/indexes/afg/diaryentry_text.txt
@@ -0,0 +1,2 @@
+{{ object.title }}
+{{ object.summary }}
View
28 afg/templates/search/search.html
@@ -0,0 +1,28 @@
+{% extends "base.html" %}
+{% block content %}
+ <h2>Search</h2>
+
+ <form method="get" action=".">
+ <table>
+ {{ form.as_table }}
+ <tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" value="Search">
+ </td>
+ </tr>
+ </table>
+
+ {% if page.object_list %}
+ <h3>Results</h3>
+
+ {% for result in page.object_list %}
+ <p>
+ <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a>
+ </p>
+ {% empty %}
+ <p>No results found.</p>
+ {% endfor %}
+ {% endif %}
+ </form>
+{% endblock %}
View
6 afg/views.py
@@ -8,16 +8,13 @@
from django.db import connection
from django.core import paginator
from django.core.urlresolvers import reverse
-from jimmypage.cache import cache_page
from afg.models import DiaryEntry, Phrase
from afg import utils
-@cache_page
def about(request):
return utils.render_request(request, "about.html")
-@cache_page
def show_entry(request, rid, template='afg/entry_page.html', api=False):
try:
entry = DiaryEntry.objects.get(report_key=rid)
@@ -71,7 +68,6 @@ def show_entry(request, rid, template='afg/entry_page.html', api=False):
'phrase_entries': phrase_entries,
})
-@cache_page
def entry_popup(request):
try:
rids = [int(r) for r in request.GET.get('rids').split(',')]
@@ -180,7 +176,6 @@ def _excerpt(haystack, needles):
return haystack[0:200]
-@cache_page
def api(request):
return utils.render_request(request, "afg/api.html")
@@ -223,7 +218,6 @@ def api(request):
'classification': ('classification', unicode),
}
-@cache_page
def search(request, about=False, api=False):
params = {}
for key in request.GET:
View
1  build_schema.sh
@@ -0,0 +1 @@
+python manage.py build_solr_schema > schema.xml
View
38 default_settings.py
@@ -1,10 +1,9 @@
-# Django settings for afgexplorer project.
-import os
-SETTINGS_ROOT = os.path.abspath(os.path.dirname(__file__))
-
DEBUG = True
TEMPLATE_DEBUG = DEBUG
+import os
+SETTINGS_ROOT = os.path.abspath(os.path.dirname(__file__))
+
ADMINS = (
# ('Your Name', 'your_email@domain.com'),
)
@@ -29,7 +28,7 @@
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
-TIME_ZONE = 'America/Chicago'
+TIME_ZONE = 'America/New_York'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
@@ -39,15 +38,15 @@
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
-USE_I18N = True
+USE_I18N = False
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale
-USE_L10N = True
+USE_L10N = False
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = os.path.join(SETTINGS_ROOT, 'media')
+MEDIA_ROOT = os.path.join(SETTINGS_ROOT, '/media/')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
@@ -57,7 +56,7 @@
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
-ADMIN_MEDIA_PREFIX = '/media/admin'
+ADMIN_MEDIA_PREFIX = '/media/admin/'
# Make this unique, and don't share it with anybody.
SECRET_KEY = 'u_6bcni=w%ll398p*7o24u9=&8_p-4z*sag$o(4s)o)*o9m@rd'
@@ -66,17 +65,17 @@
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
- 'johnny.middleware.LocalStoreClearMiddleware',
- 'johnny.middleware.QueryCacheMiddleware',
+ #'johnny.middleware.LocalStoreClearMiddleware',
+ #'johnny.middleware.QueryCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
- #'debug_toolbar.middleware.DebugToolbarMiddleware',
)
ROOT_URLCONF = 'afgexplorer.urls'
@@ -85,7 +84,7 @@
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
- os.path.join(SETTINGS_ROOT, 'templates'),
+ os.path.join(SETTINGS_ROOT, 'templates')
)
INSTALLED_APPS = (
@@ -94,14 +93,13 @@
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
+ 'django.contrib.gis',
'django.contrib.admin',
- 'johnny',
- 'jimmypage',
+ #'johnny',
+ 'haystack',
'afg',
- #'debug_toolbar',
)
-JIMMY_PAGE_CACHE_PREFIX = "jp_afg"
-CACHE_BACKEND = 'johnny.backends.memcached://127.0.0.1:11211/'
-JOHNNY_MIDDLEWARE_KEY_PREFIX = "jc_afg"
-INTERNAL_IPS = ('127.0.0.1',)
+HAYSTACK_SITECONF = 'afgexplorer.search_sites'
+HAYSTACK_SEARCH_ENGINE = 'solr'
+HAYSTACK_SOLR_URL = 'http://127.0.0.1:8983/solr'
View
8 requirements.txt
@@ -1,5 +1,7 @@
django==1.2.1
-johnny-cache
--e git://github.com/yourcelf/django-jimmypage.git#egg=django-jimmypage
-python-memcached
+-e git://github.com/toastdriven/django-haystack.git#egg=django-haystack
+pysolr
+lxml
+httplib2
django-debug-toolbar
+johnny-cache
View
7 reset_afgexplorer.sh
@@ -1,8 +1,9 @@
#!/bin/sh
-DBNAME=afg
-DBUSER=afg
+DBNAME=afg2
+DBUSER=afg2
sudo su postgres -c "dropdb $DBNAME"
sudo su postgres -c "createdb -T template_postgis -O $DBUSER $DBNAME"
-sudo su postgres -c "psql $DBNAME $DBUSER < data/afg.sql"
+python manage.py syncdb --noinput
+#sudo su postgres -c "psql $DBNAME $DBUSER < data/afg.sql"
View
209 schema.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<schema name="default" version="1.1">
+ <types>
+ <fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
+
+ <!-- Numeric field types that manipulate the value into
+ a string value that isn't human-readable in its internal form,
+ but with a lexicographic ordering the same as the numeric ordering,
+ so that range queries work correctly. -->
+ <fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
+ <fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
+
+ <fieldType name="date" class="solr.DateField" sortMissingLast="true" omitNorms="true"/>
+
+ <fieldType name="text" class="solr.TextField" positionIncrementGap="100">
+ <analyzer type="index">
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+ <!-- in this example, we will only use synonyms at query time
+ <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+ -->
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+ <filter class="solr.LowerCaseFilterFactory"/>
+ <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+ </analyzer>
+ <analyzer type="query">
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+ <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
+ <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/>
+ <filter class="solr.LowerCaseFilterFactory"/>
+ <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
+ <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+ </analyzer>
+ </fieldType>
+
+ <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+ <analyzer>
+ <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+ </analyzer>
+ </fieldType>
+ </types>
+
+ <fields>
+ <!-- general -->
+ <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
+ <field name="django_ct" type="string" indexed="true" stored="true" multiValued="false" />
+ <field name="django_id" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <dynamicField name="*_i" type="sint" indexed="true" stored="true"/>
+ <dynamicField name="*_s" type="string" indexed="true" stored="true"/>
+ <dynamicField name="*_l" type="slong" indexed="true" stored="true"/>
+ <dynamicField name="*_t" type="text" indexed="true" stored="true"/>
+ <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
+ <dynamicField name="*_f" type="sfloat" indexed="true" stored="true"/>
+ <dynamicField name="*_d" type="sdouble" indexed="true" stored="true"/>
+ <dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
+
+
+ <field name="point" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="unit_name" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="unit_name_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="classification" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="classification_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="mgrs" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="mgrs_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="text" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="affiliation" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="affiliation_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="updated_by_group" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="updated_by_group_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="enemy_kia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="enemy_kia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="complex_attack" type="boolean" indexed="true" stored="true" multiValued="false" />
+
+ <field name="complex_attack_exact" type="boolean" indexed="true" stored="true" multiValued="false" />
+
+ <field name="originator_group" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="originator_group_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="category" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="category_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="type_of_unit" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="type_of_unit_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="title" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="dcolor" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="dcolor_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="type_" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="type__exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="civilian_wia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="civilian_wia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="civilian_kia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="civilian_kia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="host_nation_wia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="host_nation_wia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="friendly_wia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="friendly_wia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="host_nation_kia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="host_nation_kia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="enemy_wia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="enemy_wia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="reporting_unit" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="reporting_unit_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="enemy_detained" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="enemy_detained_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="ccir" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="ccir_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="friendly_kia" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="friendly_kia_exact" type="slong" indexed="true" stored="true" multiValued="false" />
+
+ <field name="date" type="date" indexed="true" stored="true" multiValued="false" />
+
+ <field name="date_exact" type="date" indexed="true" stored="true" multiValued="false" />
+
+ <field name="report_key" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="region" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="region_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="summary" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="tracking_number" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="sigact" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="sigact_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ <field name="attack_on" type="text" indexed="true" stored="true" multiValued="false" />
+
+ <field name="attack_on_exact" type="string" indexed="true" stored="true" multiValued="false" />
+
+ </fields>
+
+ <!-- field to use to determine and enforce document uniqueness. -->
+ <uniqueKey>id</uniqueKey>
+
+ <!-- field for the QueryParser to use when an explicit fieldname is absent -->
+ <defaultSearchField>text</defaultSearchField>
+
+ <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
+ <solrQueryParser defaultOperator="AND" />
+</schema>
+
+
View
2  search_sites.py
@@ -0,0 +1,2 @@
+import haystack
+haystack.autodiscover()
Please sign in to comment.
Something went wrong with that request. Please try again.