diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
index acc0312b59c27e5c41eafccbcd882da3863570f7..e235dc29642ffc27070e858d8bef547e1e6daafb 100644
--- a/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
+++ b/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
@@ -35,6 +35,7 @@ import de.vipra.util.ex.ConfigException;
 import de.vipra.util.ex.DatabaseException;
 import de.vipra.util.model.ArticleFull;
 import de.vipra.util.service.MongoService;
+import de.vipra.util.service.Service.QueryBuilder;
 
 @Path("articles")
 public class ArticleResource {
@@ -52,15 +53,22 @@ public class ArticleResource {
 	@GET
 	@Produces(MediaType.APPLICATION_JSON)
 	public Response getArticles(@QueryParam("skip") final Integer skip, @QueryParam("limit") final Integer limit,
-			@QueryParam("sort") @DefaultValue("date") final String sortBy, @QueryParam("fields") final String fields) {
+			@QueryParam("sort") @DefaultValue("date") final String sortBy, @QueryParam("fields") final String fields,
+			@QueryParam("word") final String word) {
 		final ResponseWrapper<List<ArticleFull>> res = new ResponseWrapper<>();
 
 		if (res.hasErrors())
 			return res.badRequest();
 
 		try {
-			final List<ArticleFull> articles = dbArticles.getMultiple(skip, limit, sortBy,
-					StringUtils.getFields(fields));
+			final QueryBuilder query = QueryBuilder.builder().skip(skip).limit(limit).sortBy(sortBy);
+			if (fields != null && !fields.isEmpty())
+				query.fields(true, StringUtils.getFields(fields));
+
+			if (word != null && !word.isEmpty())
+				query.criteria("words.word.id", word);
+
+			final List<ArticleFull> articles = dbArticles.getMultiple(query);
 
 			if ((skip != null && skip > 0) || (limit != null && limit > 0))
 				res.addHeader("total", dbArticles.count(null));
@@ -105,16 +113,6 @@ public class ArticleResource {
 		}
 	}
 
-	@GET
-	@Produces(MediaType.APPLICATION_JSON)
-	@Path("{id}/similar")
-	public Response getSimilar(@PathParam("id") final String id, @QueryParam("skip") final Integer skip,
-			@QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("date") final String sortBy,
-			@QueryParam("fields") final String fields) {
-		// TODO implement
-		return null;
-	}
-
 	@POST
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Produces(MediaType.APPLICATION_JSON)
diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java
index 69d76ea7fe4663f4c81b8ed1681b6aed83e7672c..c7f665a9d1833a0be7ce8b366701bba6b0c5c3cc 100644
--- a/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java
+++ b/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java
@@ -105,7 +105,7 @@ public class TopicResource {
 	@Path("{id}/articles")
 	public Response getArticles(@PathParam("id") final String id, @QueryParam("skip") final Integer skip,
 			@QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("title") final String sortBy,
-			@QueryParam("fields") final String fields, @Context UriInfo uriInfo) {
+			@QueryParam("fields") final String fields, @Context final UriInfo uriInfo) {
 		final ResponseWrapper<List<ArticleFull>> res = new ResponseWrapper<>();
 		try {
 			final Topic topic = new Topic(MongoUtils.objectId(id));
@@ -129,26 +129,6 @@ public class TopicResource {
 		}
 	}
 
-	@GET
-	@Produces(MediaType.APPLICATION_JSON)
-	@Path("{id}/similar/by-words")
-	public Response similarTopicsByWords(@PathParam("id") final String id, @QueryParam("skip") final Integer skip,
-			@QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("title") final String sortBy,
-			@QueryParam("fields") final String fields) {
-		// TODO implement
-		return null;
-	}
-
-	@GET
-	@Produces(MediaType.APPLICATION_JSON)
-	@Path("{id}/similar/by-articles")
-	public Response similarTopicsByArticles(@PathParam("id") final String id, @QueryParam("skip") final Integer skip,
-			@QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("title") final String sortBy,
-			@QueryParam("fields") final String fields) {
-		// TODO implement
-		return null;
-	}
-
 	@PUT
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Produces(MediaType.APPLICATION_JSON)
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java
index 8e17e0e60defe916eb5cf689fbce5f0eb2b5b875..4cc9527af87226834080a2ea29b362e323592286 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ImportCommand.java
@@ -83,6 +83,7 @@ public class ImportCommand implements Command {
 				// preprocess text
 				final ProcessedText processedText = processor.process(article.getText());
 				article.setProcessedText(processedText.getWords());
+				article.setWords(processedText.getArticleWords());
 
 				// generate article stats
 				final ArticleStats stats = new ArticleStats();
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java b/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java
index a47d1738d536aa37154dfde1e0580791eaa84fac..8911bcd2e62df83ebe84e51af5d279521034a94a 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java
@@ -1,17 +1,33 @@
 package de.vipra.cmd.text;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+
+import de.vipra.util.CountMap;
+import de.vipra.util.model.ArticleWord;
+
 public class ProcessedText {
 
 	private final String[] words;
 	private final long originalWordCount;
 	private final long reducedWordCount;
 	private final double reductionRatio;
+	private final List<ArticleWord> articleWords;
 
 	public ProcessedText(final String text, final long wordCount) {
 		words = text.split("\\s+");
 		originalWordCount = wordCount;
 		reducedWordCount = words.length;
 		reductionRatio = 1 - ((double) reducedWordCount / wordCount);
+
+		final CountMap<String> wordCounts = new CountMap<>();
+		for (final String word : words)
+			wordCounts.count(word);
+		final List<ArticleWord> articleWords = new ArrayList<>(wordCounts.size());
+		for (final Entry<String, Integer> entry : wordCounts.entrySet())
+			articleWords.add(new ArticleWord(entry.getKey(), entry.getValue()));
+		this.articleWords = articleWords;
 	}
 
 	public String[] getWords() {
@@ -30,4 +46,8 @@ public class ProcessedText {
 		return reductionRatio;
 	}
 
+	public List<ArticleWord> getArticleWords() {
+		return articleWords;
+	}
+
 }
diff --git a/vipra-ui/app/html/articles/index.html b/vipra-ui/app/html/articles/index.html
index b37d4ad6e5686bd06fb3ea72eb98e7aca3bdb22c..681ebf3ec9d434de77843ff3c68c1d4bf19d0e2e 100644
--- a/vipra-ui/app/html/articles/index.html
+++ b/vipra-ui/app/html/articles/index.html
@@ -12,16 +12,12 @@
           <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database.
           <span ng-show="articlesTotal">
           Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sort">
+          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sortkey">
             <li value="title" class="nya-bs-option"><a>Title</a></li>
             <li value="date" class="nya-bs-option"><a>Date</a></li>
             <li value="created" class="nya-bs-option"><a>Added</a></li>
           </ol>
-          Direction
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.order">
-            <li value="+" class="nya-bs-option"><a>Ascending</a></li>
-            <li value="-" class="nya-bs-option"><a>Descending</a></li>
-          </ol>
+          <sort-dir ng-model="opts.sortdir" />
         </span>
         </div>
         <table class="table table-hover table-condensed">
diff --git a/vipra-ui/app/html/directives/sort-dir.html b/vipra-ui/app/html/directives/sort-dir.html
new file mode 100644
index 0000000000000000000000000000000000000000..155e996f9778a191c0a684d65903204d7ec4f0c6
--- /dev/null
+++ b/vipra-ui/app/html/directives/sort-dir.html
@@ -0,0 +1 @@
+<i class="pointer fa" ng-class="{'fa-sort-amount-desc':ngModel,'fa-sort-amount-asc':!ngModel}" ng-click="ngModel=!ngModel; $event.stopPropagation()"></i>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/topic-link.html b/vipra-ui/app/html/directives/topic-link.html
index 3423ff2bc20b5dde54324f3b2990914a202e29de..49ccb9e20545839284bb76e6f15aa5240fc6d337 100644
--- a/vipra-ui/app/html/directives/topic-link.html
+++ b/vipra-ui/app/html/directives/topic-link.html
@@ -1,7 +1,7 @@
 <span>
   <a class="topic-link" ui-sref="topics.show({id:topic.id})">
     <span ng-bind="topic.name"></span>
-<ng-transclude/>
-</a>
-<topic-menu topic="topic" />
+    <ng-transclude/>
+  </a>
+  <topic-menu topic="topic" right="true" />
 </span>
diff --git a/vipra-ui/app/html/directives/topic-menu.html b/vipra-ui/app/html/directives/topic-menu.html
index 8d3b33b220ada75728b5c6148f85f33ae72d1d63..f08e2a20b359357247851acfbbf4842f8e1c76f4 100644
--- a/vipra-ui/app/html/directives/topic-menu.html
+++ b/vipra-ui/app/html/directives/topic-menu.html
@@ -2,7 +2,7 @@
   <a data-toggle="dropdown">
     <i class="fa fa-caret-down"></i>
   </a>
-  <ul class="dropdown-menu dropdown-menu-right">
+  <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
     <li><a ui-sref="topics.show({id:topic.id})">Show</a></li>
     <li><a ui-sref="network({type:'topics',id:topic.id})">Network</a></li>
     <li><a ui-sref="topics.show.articles({id:topic.id})">Articles</a></li>
diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html
index a0ea30eca7e9a3c47417785e58d1c2c8473c4574..f6d7e25a2e284c75d982789798e6e5cbd256fa96 100644
--- a/vipra-ui/app/html/explorer.html
+++ b/vipra-ui/app/html/explorer.html
@@ -12,8 +12,8 @@
       <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'fallingRelevance'" title="Sort by falling relevance">&#8600;</a>
       <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'risingRelevance'" title="Sort by rising relevance">&#8599;</a>
       <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'risingDecayRelevance'" title="Sort by rising relevance with decay">&#8605;</a>
-      <a class="btn btn-sm btn-link" ng-click="opts.sortdir=!opts.sortdir">
-        <i class="fa" ng-class="{'fa-sort-amount-desc':opts.sortdir,'fa-sort-amount-asc':!opts.sortdir}"></i>
+      <a class="btn btn-sm btn-link btn-plain" ng-click="opts.sortdir=!opts.sortdir">
+        <sort-dir ng-model="opts.sortdir" />
       </a>
     </div>
     <div class="btn-group btn-group-justified">
@@ -22,13 +22,16 @@
     </div>
     <ul class="list-unstyled topic-choice">
       <li ng-repeat="topic in topics | orderBy:opts.sorttopics:opts.sortdir | filter:search">
-        <div class="checkbox checkbox-condensed" ng-class="{selected:topic.selected}" bs-popover popover-title="{{::topic.name}}" popover-template="partials/topic-popover.html">
+        <div class="checkbox checkbox-condensed" ng-class="{selected:topic.selected}">
           <span class="valuebar" ng-style="{width:topicCurrValue(topic)}"></span>
           <input type="checkbox" ng-model="topic.selected" ng-attr-id="{{::topic.id}}" ng-change="redrawGraph()">
           <label class="check" ng-attr-for="{{::topic.id}}">
-            <span class="ellipsis" ng-bind="::topic.name"></span>
+            <topic-menu topic="topic" />
+            <span class="ellipsis topic">
+              <span ng-bind="::topic.name"></span>
+            </span>
           </label>
-          <span class="colorbox" style="background:{{::topic.color}}"></span>
+          <span class="colorbox" style="background:{{::topic.color}}" bs-popover popover-title="{{::topic.name}}" popover-template="partials/topic-popover.html" popover-delay="500"></span>
         </div>
       </li>
     </ul>
diff --git a/vipra-ui/app/html/topics/articles.html b/vipra-ui/app/html/topics/articles.html
index c27bec67acd32dc01dc8fcb3335bf2fdb91c1df8..c7ecd073bd87f7782a620bbee998451e4b7a95ae 100644
--- a/vipra-ui/app/html/topics/articles.html
+++ b/vipra-ui/app/html/topics/articles.html
@@ -26,16 +26,12 @@
           <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database.
           <span ng-show="articlesTotal">
           Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sort">
+          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sortkey">
             <li value="title" class="nya-bs-option"><a>Title</a></li>
             <li value="date" class="nya-bs-option"><a>Date</a></li>
             <li value="created" class="nya-bs-option"><a>Added</a></li>
           </ol>
-          Direction
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.order">
-            <li value="+" class="nya-bs-option"><a>Ascending</a></li>
-            <li value="-" class="nya-bs-option"><a>Descending</a></li>
-          </ol>
+          <sort-dir ng-model="opts.sortdir" />
         </span>
         </div>
         <table class="table table-hover table-condensed">
diff --git a/vipra-ui/app/html/topics/index.html b/vipra-ui/app/html/topics/index.html
index 413d3d26e797e25071bd08c2984119ffe353af87..3a8babc5d093749827f395fb55930e6bbf233f0c 100644
--- a/vipra-ui/app/html/topics/index.html
+++ b/vipra-ui/app/html/topics/index.html
@@ -12,15 +12,11 @@
           <ng-pluralize count="topicsTotal||0" when="{0:'no topics',1:'1 topic',other:'{} topics'}"></ng-pluralize> in the database.
           <span ng-show="topicsTotal">
           Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sort">
+          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sortkey">
             <li value="name" class="nya-bs-option"><a>Name</a></li>
             <li value="created" class="nya-bs-option"><a>Added</a></li>
           </ol>
-          Direction
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.order">
-            <li value="+" class="nya-bs-option"><a>Ascending</a></li>
-            <li value="-" class="nya-bs-option"><a>Descending</a></li>
-          </ol>
+          <sort-dir ng-model="opts.sortdir" />
         </span>
         </div>
         <table class="table table-hover table-condensed">
diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js
index 8012e8e96486f85cb64e07690c98b772ccd29db7..9c460c9da4dc6aba1b2666692516af8551276463 100644
--- a/vipra-ui/app/js/controllers.js
+++ b/vipra-ui/app/js/controllers.js
@@ -307,6 +307,7 @@
 
       $scope.opts = {
         sorttopics: 'name',
+        sortdir: false,
         seqstyle: 'absolute',
         chartstyle: 'areaspline',
         chartstack: 'none'
@@ -421,18 +422,18 @@
     function($scope, $state, $location, ArticleFactory) {
 
       $scope.opts = {
-        sort: 'date',
-        order: '+'
+        sortkey: 'date',
+        sortdir: true
       };
 
       $scope.page = Math.max($location.search().page || 1, 1);
       $scope.limit = 100;
 
-      $scope.$watchGroup(['page', 'opts.sort', 'opts.order'], function() {
+      $scope.$watchGroup(['page', 'opts.sortkey', 'opts.sortdir'], function() {
         ArticleFactory.query({
           skip: ($scope.page - 1) * $scope.limit,
           limit: $scope.limit,
-          sort: $scope.opts.order + $scope.opts.sort
+          sort: ($scope.opts.sortdir ? '' : '-') + $scope.opts.sortkey
         }, function(data, headers) {
           $scope.articles = data;
           $scope.articlesTotal = headers("V-Total");
@@ -520,18 +521,18 @@
     function($scope, $location, TopicFactory) {
 
       $scope.opts = {
-        sort: 'name',
-        order: '+'
+        sortkey: 'name',
+        sortdir: true
       };
 
       $scope.page = Math.max($location.search().page || 1, 1);
       $scope.limit = 100;
 
-      $scope.$watchGroup(['page', 'opts.sort', 'opts.order'], function() {
+      $scope.$watchGroup(['page', 'opts.sortkey', 'opts.sortdir'], function() {
         TopicFactory.query({
           skip: ($scope.page - 1) * $scope.limit,
           limit: $scope.limit,
-          sort: $scope.opts.order + $scope.opts.sort
+          sort: ($scope.opts.sortdir ? '' : '-') + $scope.opts.sortkey
         }, function(data, headers) {
           $scope.topics = data;
           $scope.topicsTotal = headers("V-Total");
@@ -638,19 +639,19 @@
     function($scope, $stateParams, $location, TopicFactory) {
 
       $scope.opts = {
-        sort: 'title',
-        order: '+'
+        sortkey: 'title',
+        sortdir: true
       };
 
       $scope.page = Math.max($location.search().page || 1, 1);
       $scope.limit = 100;
 
-      $scope.$watchGroup(['page', 'opts.sort', 'opts.order'], function() {
+      $scope.$watchGroup(['page', 'opts.sortkey', 'opts.sortdir'], function() {
         TopicFactory.articles({
           id: $stateParams.id,
           skip: ($scope.page - 1) * $scope.limit,
           limit: $scope.limit,
-          sort: $scope.opts.order + $scope.opts.sort
+          sort: ($scope.opts.sortdir ? '' : '-') + $scope.opts.sortkey
         }, function(data, headers) {
           $scope.articles = data;
           $scope.articlesTotal = headers("V-Total");
diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js
index 3e8c67c7fdb580d79c217cf825bc2a061f35c5bc..404d439da573128488eaddb27a4a026b2b613db7 100644
--- a/vipra-ui/app/js/directives.js
+++ b/vipra-ui/app/js/directives.js
@@ -203,12 +203,13 @@
   app.directive('topicMenu', function() {
     return {
       scope: {
-        topic: '='
+        topic: '=',
+        right: '@'
       },
       restrict: 'E',
-      replace: true,
       templateUrl: 'html/directives/topic-menu.html',
       link: function($scope) {
+        $scope.dropdownRight = $scope.right === 'true';
         $scope.renameTopic = function() {
           bootbox.prompt({
             title: 'Rename topic',
@@ -224,4 +225,15 @@
     };
   });
 
+  app.directive('sortDir', function() {
+    return {
+      scope: {
+        ngModel: '='
+      },
+      restrict: 'E',
+      replace: true,
+      templateUrl: 'html/directives/sort-dir.html'
+    }
+  });
+
 })();
diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less
index 7d81389997ea62e4ffc6ea90db9bee4aaee5fba8..8f1d3a1c11d2339f5dc6ab68201a1f07389e3498 100644
--- a/vipra-ui/app/less/app.less
+++ b/vipra-ui/app/less/app.less
@@ -275,6 +275,19 @@ a:hover {
         margin-left: -18px;
       }
     }
+    .topic {
+      padding-left: 15px;
+    }
+    .popover-area {
+      position: absolute;
+      right: 0;
+      top: 0;
+      width: 250px;
+      height: 100%;
+    }
+    topic-menu {
+      position: absolute;
+    }
   }
   .colorbox {
     position: absolute;
@@ -350,7 +363,11 @@ a:hover {
   }
 }
 
-.inline-block {
+.btn.btn-plain {
+  color: #333;
+}
+
+topic-menu {
   display: inline-block;
 }
 
diff --git a/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java b/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java
index fbad9e2a6cbc55b5d68b1a0f0c48b9c6562e9160..60eb7dc6cfaf1ea9f34a923f4078b5210cc4f119 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java
@@ -1,7 +1,5 @@
 package de.vipra.util.model;
 
-import java.io.File;
-import java.io.IOException;
 import java.io.Serializable;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -22,7 +20,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import de.vipra.util.Constants;
-import de.vipra.util.FileUtils;
 import de.vipra.util.MongoUtils;
 import de.vipra.util.NestedMap;
 import de.vipra.util.StringUtils;
@@ -32,7 +29,7 @@ import de.vipra.util.an.QueryIgnore;
 @SuppressWarnings("serial")
 @Entity(value = "articles", noClassnameStored = true)
 @Indexes({ @Index("title"), @Index("date"), @Index("-created") })
-public class ArticleFull extends FileModel<ObjectId> implements Serializable {
+public class ArticleFull implements Model<ObjectId>, Serializable {
 
 	public static final Logger log = LoggerFactory.getLogger(ArticleFull.class);
 
@@ -61,6 +58,10 @@ public class ArticleFull extends FileModel<ObjectId> implements Serializable {
 	@QueryIgnore(multi = true)
 	private List<SimilarArticle> similarArticles;
 
+	@Embedded
+	@QueryIgnore(all = true)
+	private List<ArticleWord> words;
+
 	@Embedded
 	@QueryIgnore(multi = true)
 	private ArticleStats stats;
@@ -173,6 +174,14 @@ public class ArticleFull extends FileModel<ObjectId> implements Serializable {
 		this.similarArticles = similarArticles;
 	}
 
+	public List<ArticleWord> getWords() {
+		return words;
+	}
+
+	public void setWords(final List<ArticleWord> words) {
+		this.words = words;
+	}
+
 	public ArticleStats getStats() {
 		return stats;
 	}
@@ -211,18 +220,6 @@ public class ArticleFull extends FileModel<ObjectId> implements Serializable {
 		meta.put(key, value);
 	}
 
-	@Override
-	public void fromFile(final File file) throws IOException {
-		final List<String> lines = FileUtils.readFile(file);
-		setTitle(lines.get(0));
-		setText(StringUtils.join(lines.subList(1, lines.size())));
-	}
-
-	@Override
-	public String toFileString() {
-		return getTitle() + "\n" + getText();
-	}
-
 	@PrePersist
 	public void prePersist() {
 		modified = new Date();
diff --git a/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java b/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java
new file mode 100644
index 0000000000000000000000000000000000000000..023d3879001d2a63a00115d2e8db27824858e1d7
--- /dev/null
+++ b/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java
@@ -0,0 +1,48 @@
+package de.vipra.util.model;
+
+import java.io.Serializable;
+
+import org.mongodb.morphia.annotations.Embedded;
+
+@SuppressWarnings("serial")
+@Embedded
+public class ArticleWord implements Comparable<ArticleWord>, Serializable {
+
+	private Word word;
+
+	private Integer count;
+
+	public ArticleWord() {}
+
+	public ArticleWord(final String word, final int count) {
+		this.word = new Word(word);
+		this.count = count;
+	}
+
+	public Word getWord() {
+		return word;
+	}
+
+	public void setWord(final Word word) {
+		this.word = word;
+	}
+
+	public Integer getCount() {
+		return count;
+	}
+
+	public void setCount(final Integer count) {
+		this.count = count;
+	}
+
+	@Override
+	public int compareTo(final ArticleWord o) {
+		return count.compareTo(o.getCount());
+	}
+
+	@Override
+	public String toString() {
+		return "ArticleWord [word=" + word + ", count=" + count + "]";
+	}
+
+}
diff --git a/vipra-util/src/main/java/de/vipra/util/model/FileModel.java b/vipra-util/src/main/java/de/vipra/util/model/FileModel.java
deleted file mode 100644
index aa681bd69818e8f48062ba429ca3a5560b8db2a8..0000000000000000000000000000000000000000
--- a/vipra-util/src/main/java/de/vipra/util/model/FileModel.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.vipra.util.model;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.commons.io.FileUtils;
-
-import de.vipra.util.Constants;
-
-@SuppressWarnings("serial")
-public abstract class FileModel<IdType> implements Model<IdType> {
-
-	public void writeToFile(final File file) throws IOException {
-		FileUtils.writeStringToFile(file, toFileString(), Constants.FILEBASE_ENCODING, false);
-	}
-
-	public abstract void fromFile(File file) throws IOException;
-
-	public abstract String toFileString();
-
-}