diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51bc4a3f4de7c0b193406747631642b3e2b7b5e6..e2d7d3f738a4ce5a4ce1fe04784edb409f95c257 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -52,8 +52,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * a `role` argument for `get_entity_by_name` and `get_entity_by_id`
 
 ### Changed ###
-* `in` operator now test whether a parent with the appropriate ID, name or both is in `ParentList`
-* `in` operator now test whether a parent with the appropriate ID, name or both is in `PropertyList`
 
 * Using environment variable PYLINKAHEADINI instead of PYCAOSDBINI.
 
diff --git a/src/linkahead/__init__.py b/src/linkahead/__init__.py
index cd54f8f4e05326579521fbbf226f027d32fa616e..567748e3b3a58fb73b91f652d82ed10f818d6014 100644
--- a/src/linkahead/__init__.py
+++ b/src/linkahead/__init__.py
@@ -42,7 +42,7 @@ from .common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER, LIST,
                               REFERENCE, TEXT)
 # Import of the basic  API classes:
 from .common.models import (ACL, ALL, FIX, NONE, OBLIGATORY, RECOMMENDED,
-                            SUGGESTED, Container, DropOffBox, Entity, File,
+                            SUGGESTED, Container, DropOffBox, Entity, File, Parent,
                             Info, Message, Permissions, Property, Query,
                             QueryTemplate, Record, RecordType, delete,
                             execute_query, get_global_acl,
diff --git a/src/linkahead/common/models.py b/src/linkahead/common/models.py
index f537a34bfe902fc8fa4991a0bb26a6d2d7e7cb9f..78988bd1bf14c557aad5020b1b7a22962d106a68 100644
--- a/src/linkahead/common/models.py
+++ b/src/linkahead/common/models.py
@@ -2522,15 +2522,23 @@ class PropertyList(list):
 
         return xml2str(xml)
 
-    def __contains__(self, prop):
-        missing = False
-        if prop.name is not None:
-            if prop.name not in self._element_by_name:
-                missing = True
-        if prop.id is not None:
-            if str(prop.id) not in self._element_by_id:
-                missing = True
-        return not missing
+    def filter(self, pid:Union[str, int]=None, name:str =None, prop:Property=None):
+        """
+        Filters all Properties from this PropertyList that match either name or ID.
+
+        You can provide name and or ID via the corresponding arguments or you
+        pass a Property object to this function.
+
+        Parameters
+        ----------
+            pid: Union[str,int], ID of the Properties to be returned
+            name: str, name of the Properties to be returned
+            prop: Property, name of the Properties to be returned
+        Returns
+        -------
+            list, a list with all matching Properties
+        """
+        return _filter_entity_list(self, "Property", pid=pid, name=name, element=prop)
 
     def _get_entity_by_cuid(self, cuid: str):
         '''
@@ -2610,11 +2618,6 @@ class ParentList(list):
         super().__init__(*args, **kwargs)
         self._element_by_name = dict()
         self._element_by_id = dict()
-        for el in self:
-            if el.name is not None:
-                self._element_by_name[el.name] = el
-            if el.id is not None:
-                self._element_by_name[str(el.id)] = el
 
     def extend(self, parents):
         self.append(parents)
@@ -2625,15 +2628,9 @@ class ParentList(list):
         if isinstance(parent, list):
             for p in parent:
                 self.append(p)
-
             return
 
         if isinstance(parent, Entity):
-            if parent.id:
-                self._element_by_id[str(parent.id)] = parent
-
-            if parent.name:
-                self._element_by_name[parent.name] = parent
             list.append(self, parent)
         else:
             raise TypeError("Argument was not an Entity")
@@ -2675,17 +2672,34 @@ class ParentList(list):
 
         return xml2str(xml)
 
-    def __contains__(self, parent):
-        missing = False
-        if parent.name is not None:
-            if parent.name not in self._element_by_name:
-                missing = True
-        if parent.id is not None:
-            if str(parent.id) not in self._element_by_id:
-                missing = True
-        return not missing
+    def filter(self, pid:Union[str, int]=None, name:str =None, parent:Parent=None):
+        """
+        Filters all Parents from this ParentList that match either name or ID.
+
+        You can provide name and or ID via the corresponding arguments or you
+        pass a Parent object to this function.
+
+        Returns
+        -------
+            a list with all matching Parents
+        """
+        return _filter_entity_list(self, "Parent", pid=pid, name=name, element=parent)
 
     def remove(self, parent: Union[Entity, int, str]):
+        """
+        Remove first occurrence of parent.
+
+        Parameters
+        ----------
+        parent: Union[Entity, int, str], the parent to be removed identified via ID or name. If a
+        Parent object is provided the ID and then the name is used to identify the parent to be
+        removed.
+
+        Returns
+        -------
+        None
+        """
+
         if isinstance(parent, Entity):
             if parent in self:
                 list.remove(self, parent)
@@ -2703,11 +2717,11 @@ class ParentList(list):
                     # by name
 
                     for e in self:
-                        if e.name is not None and e.name == parent.name:
+                        if e.name is not None and e.name.lower() == parent.name.lower():
                             list.remove(self, e)
 
                             return
-        elif hasattr(parent, "encode"):
+        elif isinstance(parent, str):
             # by name
 
             for e in self:
@@ -5433,3 +5447,30 @@ def delete(ids: Union[list[int], range], raise_exception_on_error: bool = True):
         c.append(Entity(id=ids))
 
     return c.delete(raise_exception_on_error=raise_exception_on_error)
+
+def _filter_entity_list(listobject, element_type, pid:Union[str, int]=None, name:str =None, element:Any=None):
+        """
+        Filterss all elements from the given list that match either name or ID.
+
+        You can provide name and or ID via the corresponding arguments or you
+        pass an  object to this function that has id and/or name.
+
+        Returns
+        -------
+            a list with all matching elements
+        """
+        if element is not None:
+            if pid is not None or name is not None:
+                raise ValueError(f"Please provide either a {element_type} or one of "
+                                 "pid or name")
+            pid = element.id
+            name = element.name
+
+        candidates = []
+        if name is not None:
+            candidates.extend(
+                [p for p in listobject if p.name is not None and p.name.lower() == name.lower()])
+        if pid is not None:
+            candidates.extend(
+                [p for p in listobject if p.id == pid])
+        return candidates
diff --git a/unittests/test_entity.py b/unittests/test_entity.py
index 87ae606ce10db7ce4411e929d66a54bc19c2dffd..9c7816a1beefa56a86dd973e63551133e0f22e22 100644
--- a/unittests/test_entity.py
+++ b/unittests/test_entity.py
@@ -28,7 +28,7 @@ import unittest
 from pytest import raises
 
 import linkahead
-from linkahead import (INTEGER, Entity, Property, Record, RecordType,
+from linkahead import (INTEGER, Entity, Property, Record, RecordType, Parent,
                        configure_connection)
 from linkahead.connection.mockup import MockUpServerConnection
 from lxml import etree
@@ -105,50 +105,43 @@ def test_parent_list():
     p1 = RecordType(name="A")
     pl = linkahead.common.models.ParentList([p1])
     assert p1 in pl
-    assert RecordType(name="A") in pl
-    assert pl.index(RecordType(name="A")) == 0
+    assert pl.index(p1) == 0
+    assert RecordType(name="A") not in pl
     assert RecordType(id=101) not in pl
-    pl.append(RecordType(id=101))
-    assert RecordType(name="A") in pl
-    assert RecordType(id=101) in pl
+    p2 = RecordType(id=101)
+    pl.append(p2)
+    assert p2 in pl
     assert len(pl) == 2
-    assert pl.index(RecordType(id=101))
-    assert RecordType(id=102) not in pl
-    pl.append(RecordType(id=103, name='B'))
-    assert RecordType(name="A") in pl
-    assert RecordType(name="B") in pl
-    assert RecordType(id=101) in pl
-    assert RecordType(id=103) in pl
+    assert p1 in pl.filter(name="A")
+    assert p2 in pl.filter(pid=101)
+    assert p2 in pl.filter(pid=101, name="A")
+    assert p1 in pl.filter(pid=101, name="A")
+    assert p1 in pl.filter(parent=Parent(id=101, name="A"))
+    assert p2 in pl.filter(parent=Parent(id=101, name="A"))
+    p3 = RecordType(id=103, name='B')
+    pl.append(p3)
     assert len(pl) == 3
-    assert pl.index(RecordType(id=103, name='B')) == 2
-    assert pl.index(RecordType(id=103)) == 2
-    assert pl.index(RecordType(name='B')) == 2
-    assert RecordType(id=105, name="B") not in pl
+    assert p3 in pl.filter(name="B")
+    assert p3 in pl.filter(pid=103)
 
     # test removal
     # remove by id only, even though element in parent list has name and id
     pl.remove(RecordType(id=103))
     assert len(pl) == 2
-    assert RecordType(name='B') not in pl
-    assert RecordType(id=103) not in pl
+    assert p3 not in pl
+    assert p2 in pl
+    assert p1 in pl
     # Same for removal by name
-    pl.append(RecordType(id=103, name='B'))
+    pl.append(p3)
     assert len(pl) == 3
     pl.remove(RecordType(name='B'))
     assert len(pl) == 2
-    assert RecordType(name='B') not in pl
-    assert RecordType(id=103) not in pl
-    # And an error if the element is wrongly specified
-    pl.append(RecordType(id=103, name='B'))
-    assert len(pl) == 3
-    with raises(ValueError) as ve:
+    assert p3 not in pl
+    # And an error if no suitable element can be found
+    with raises(KeyError) as ve:
         pl.remove(RecordType(id=105, name='B'))
-    assert "not in list" in str(ve.value)
-    assert len(pl) == 3
-    with raises(ValueError) as ve:
-        pl.remove(RecordType(id=103, name='C'))
-    assert "not in list" in str(ve.value)
-    assert len(pl) == 3
+    assert "not found" in str(ve.value)
+    assert len(pl) == 2
 
     # TODO also check other built-in list functions: insert, pop, clear, count
     # TODO also check pl1 == pl2
@@ -159,22 +152,28 @@ def test_parent_list():
     # TODO what is with the ambiguous RecordType(name='A', id=101) in pl?
 
 
+
+
 def test_property_list():
-    # TODO: Resolve parent-list TODOs, the transfer to here.
+    # TODO: Resolve parent-list TODOs, then transfer to here.
     # TODO: What other considerations have to be done with properties?
     p1 = Property(name="A")
     pl = linkahead.common.models.PropertyList()
     pl.append(p1)
     assert p1 in pl
-    assert Property(name="A") in pl
-    assert not Property(id=101) in pl
-    pl.append(Property(id=101))
-    assert Property(name="A") in pl
-    assert Property(id=101) in pl
-    assert not Property(id=102) in pl
-    pl.append(Property(id=103, name='B'))
-    assert Property(name="A") in pl
-    assert Property(name="B") in pl
-    assert Property(id=101) in pl
-    assert Property(id=103) in pl
-    assert not Property(id=105, name="B") in pl
+    assert Property(id=101) not in pl
+    p2 = Property(id=101)
+    pl.append(p2)
+    assert p1 in pl
+    assert p2 in pl
+    p3 = Property(id=103, name='B')
+    pl.append(p3)
+
+    assert p1 in pl.filter(name="A")
+    assert p2 in pl.filter(pid=101)
+    assert p2 in pl.filter(pid=101, name="A")
+    assert p1 in pl.filter(pid=101, name="A")
+    assert p1 in pl.filter(prop=Property(id=101, name="A"))
+    assert p2 in pl.filter(prop=Property(id=101, name="A"))
+    assert p3 in pl.filter(name="B")
+    assert p3 in pl.filter(pid=103)