1 Reply Latest reply on Mar 5, 2014 11:46 AM by Luke Noel-Storr

    Is Infinispan a suitable alternative to EAV?

    Luke Noel-Storr Newbie

      So, I'm facing the classic EAV problem.  I have some entities that have user definable attributes and values, and I need to be able to run queries across them.

       

      Snippets of what I read about Inifinispan make me think it may be a good solution to this problem, but I then fail to find any concrete examples, or even any real clues as to where I might start.  Infinispan seems to have a phenomenal amount of documentation for an open source project, but I'm struggling to find any use cases or examples or tutorial about different uses.

       

      For (a really bad) example, I may have a Car entity, where users have defined the following fields:

       

      • year
      • alloy wheels
      • colour
      • size

       

      These are user defined fields, so would be stored in a map type structure in the code, rather than being accessible by getter method on an object.

       

      They might then want to find the set of all blue family sized cars from 2012, with alloy wheels.

       

      The first track I went down was using the infinispan querying module; however, I can't see a way of getting that to work unless I have an object with fields or methods matching the properties I want to search on.

       

      The next idea was to use map reduce to search for the items. Would this be a good solution, and how would it compare performance wise to using a relational database? (for reference, in a relational database I would actually be using either a sparse table - so generic field_1, field_2, ... field_n columns - or an xml column type, rather than the more standard EAV model).

       

      I'd be very grateful of any pointers, or equally grateful if someone could let me know that it's not really a good fit, and I should stop wasting my time and move on.

        • 1. Re: Is Infinispan a suitable alternative to EAV?
          Luke Noel-Storr Newbie

          OK, I managed to get somewhere with this, as I found a way to index the properties of the map.

           

          My solution was to make use of a Class Bridge to map the properties in the maps to indexed fields, and to build up a SearchMapping programatically as follows:

           

                  SearchMapping mapping = new SearchMapping();
                  IndexedMapping entity = mapping.entity(Entity.class).indexed();
          
                  for (String property : properties) {
                      entity.classBridge(EntityPropertyClassBridge.class)
                          .name(property)
                          .param("property", property);
                  }
          

           

          Where EntityPropertyClassBridge has the following set method:

           

                  public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
                      final Field field = new Field(
                          name,
                          objectToString(((Entity) value).properties.get(property)),
                          luceneOptions.getStore(),
                          luceneOptions.getIndex(),
                          luceneOptions.getTermVector());
          
          
                      field.setBoost(luceneOptions.getBoost());
          
          
                      document.add(field);
                  }
          

          This seems to do the trick, and I can now search on the properties of the map.  I found a couple of issues so far, though:

           

          1. If we need to add a new type of property, then we need to build a new mapping.  The only way I have found to do this, and have it be applied, is to shutdown the CacheManger and start a new one with the new mapping applied for indexing the given cache.  This seems less than ideal, and I'm also unsure what the overheads might be.
          2. I seem to be able to use a hibernate QueryBuilder (searchManager.buildQueryBuilderForClass(Entity.class).get()) to build queries without an issue, but if I try and use an Infinispan QueryFactory (searchManager..getQueryFactory()) to build the queries, then it cannot find the fields defined using classBridge().

           

          I'm also still not sure if trying to do this is A Good Idea™.