docs: def add(self, key, **kwargs):
          """ Add a key to the vector, do nothing if the key is already present
          
          >>> doc = Doc(docnum='1')
          >>> doc.terms = Text(multi=True, attrs={'tf': Numeric(default=1, min=0)}) 
          >>> doc.terms.add('chat')
          >>> doc.terms.add('dog', tf=2)
          >>> doc.terms.tf.values()
          [1, 2]
          
          >>> doc.terms.add('mouse', comment="a small mouse")
          Traceback (most recent call last):
          ...
          ValueError: Invalid attribute name: 'comment'
          
          >>> doc.terms.add('mouse', tf=-2)
          Traceback (most recent call last):
          ValidationError: ['Ensure this value ("-2") is greater than or equal to 0.']
          """
          if not self.has(key):
              # check if kwargs are valid
              for attr_name, value in six.iteritems(kwargs):
                  if attr_name not in self._ftype.attrs:
                      raise ValueError("Invalid attribute name: '%s'" % attr_name)
                  self._ftype.attrs[attr_name].validate(value)
              # add the key
              self._keys[key] = len(self._keys)
              # append attributes
              for name, attr_type in six.iteritems(self._ftype.attrs):
                  attr_field = DocField.FromType(attr_type)
                  if name in kwargs:
                      attr_field.set(kwargs[name])
                  self._attrs[name].append(attr_field)