0 votes

Is it possible to filter a MongoDB on the value of a field whose value is a list of dictionaries?

I want to know if it is possible to get all the documents in a MongoDB database by querying on the elements of a field whose value is a list. For example here q2.Results has a list of comments and I would like to get all the documents where the UserNickname of the person who wrote the comment is Jackobear :

{
  "_id": {
    "$oid": "5fd5e617260828c7646000aa"
  },
  "q2": {
    "Id": "q2",
    "Locale": "fr_FR",
    "Results": [
      {
        "Id": "163069310",
        "CID": "eb523c23-980d-5661-b9d0-c6dc1028fa42",
        "SourceClient": "sephora-fr",
        "Badges": {
          "loyaltyYes--Im-a-VIB-Rouge": {
            "ContentType": "REVIEW",
            "Id": "loyaltyYes--Im-a-VIB-Rouge",
            "BadgeType": "Custom"
          }
        },
        "BadgesOrder": [
          "loyaltyYes--Im-a-VIB-Rouge"
        ],
        "LastModeratedTime": "2020-09-22T12:00:18.000+00:00",
        "LastModificationTime": "2020-12-10T14:36:16.000+00:00",
        "ProductId": "P3742199",
        "CampaignId": "BV_PIE_ONLINE",
        "ContextDataValuesOrder": [
          "Gender",
          "Eyes",
          "Skin"
        ],
        "UserLocation": "Paris",
        "AuthorId": "78948942",
        "ContentLocale": "fr_FR",
        "IsFeatured": false,
        "TotalInappropriateFeedbackCount": {
          "$numberInt": "0"
        },
        "TotalClientResponseCount": {
          "$numberInt": "0"
        },
        "TotalCommentCount": {
          "$numberInt": "0"
        },
        "Rating": {
          "$numberInt": "5"
        },
        "IsRatingsOnly": false,
        "IsRecommended": true,
        "Helpfulness": {
          "$numberDouble": "1.0"
        },
        "TotalFeedbackCount": {
          "$numberInt": "2"
        },
        "TotalNegativeFeedbackCount": {
          "$numberInt": "0"
        },
        "TotalPositiveFeedbackCount": {
          "$numberInt": "2"
        },
        "ModerationStatus": "APPROVED",
        "SubmissionId": "r23232-fr__16007743UA3Zr3O9L5",
        "SubmissionTime": "2020-09-22T11:32:57.000+00:00",
        "ReviewText": "J’adore, il sent le bord de mer une ressemblance avec le parfum Kenzo",
        "Title": "Très bon parfum",
        "UserNickname": "Jackobear",
        "ContextDataValues": {
          "Gender": {
            "Value": "Male",
            "Id": "Gender"
          },
          "Skin": {
            "Value": "Normale",
            "Id": "Skin"
          },
          "Eyes": {
            "Value": "Marrons",
            "Id": "Eyes"
          }
        },
        "Videos": [],
        "Pros": null,
        "InappropriateFeedbackList": [],
        "SecondaryRatings": {},
        "ClientResponses": [],
        "Photos": [],
        "Cons": null,
        "IsSyndicated": false,
        "SecondaryRatingsOrder": [],
        "AdditionalFields": {},
        "RatingRange": {
          "$numberInt": "5"
        },
        "TagDimensions": {},
        "AdditionalFieldsOrder": [],
        "ProductRecommendationIds": [],
        "CommentIds": [],
        "TagDimensionsOrder": []
      },
      {
        "Id": "129228166",
        "CID": "66aec0c2-04b0-57d2-aa9f-ac3b7ecb91df",
        "SourceClient": "sephora-fr",
        "Badges": {
          "loyaltyYes--Im-a-beauty-insider": {
            "ContentType": "REVIEW",
            "Id": "loyaltyYes--Im-a-beauty-insider",
            "BadgeType": "Custom"
          }
        },
        "BadgesOrder": [
          "loyaltyYes--Im-a-beauty-insider"
        ],
        "LastModeratedTime": "2019-06-12T00:15:07.000+00:00",
        "LastModificationTime": "2020-02-07T10:11:38.000+00:00",
        "ProductId": "P3742199",
        "CampaignId": "BV_REVIEW_DISPLAY",
        "ContextDataValuesOrder": [
          "Gender",
          "Age",
          "Eyes",
          "Skin"
        ],
        "UserLocation": "Bayeux",
        "AuthorId": "78051240",
        "ContentLocale": "fr_FR",
        "IsFeatured": false,
        "InappropriateFeedbackList": [
          {
            "AuthorId": "ztn5x2jvnf5u8llq2jagt7j4mp",
            "SubmissionTime": "2019-06-11T23:12:44.000+00:00"
          },
          {
            "AuthorId": "zpebdw7hh48w5zpr3778nx2hgg",
            "SubmissionTime": "2019-06-06T23:20:57.000+00:00"
          },
          {
            "AuthorId": "zkvy1qeaaz8s2znk6kesfg3dnb",
            "SubmissionTime": "2019-06-03T20:01:34.000+00:00"
          }
        ],
        "TotalInappropriateFeedbackCount": {
          "$numberInt": "3"
        },
        "TotalClientResponseCount": {
          "$numberInt": "0"
        },
        "TotalCommentCount": {
          "$numberInt": "0"
        },
        "Rating": {
          "$numberInt": "5"
        },
        "IsRatingsOnly": false,
        "IsRecommended": true,
        "Helpfulness": {
          "$numberDouble": "0.8999999761581421"
        },
        "TotalFeedbackCount": {
          "$numberInt": "40"
        },
        "TotalNegativeFeedbackCount": {
          "$numberInt": "4"
        },
        "TotalPositiveFeedbackCount": {
          "$numberInt": "36"
        },
        "ModerationStatus": "APPROVED",
        "SubmissionId": "halilss25hcanccb0yj6nxvpk",
        "SubmissionTime": "2019-06-03T11:43:04.000+00:00",
        "ReviewText": "Un parfum enivrant mais pas entêtant, la note de tête est exquise et très fraîche, parfaite pour l'été. Vous devriez vendre ce parfum dans plus de sephora et avec plus de stock!!",
        "Title": "Parfait pour l'été",
        "UserNickname": "Abraxas",
        "ContextDataValues": {
          "Age": {
            "Value": "18to24",
            "Id": "Age"
          },
          "Gender": {
            "Value": "Female",
            "Id": "Gender"
          },
          "Skin": {
            "Value": "Grasse",
            "Id": "Skin"
          },
          "Eyes": {
            "Value": "Bleus",
            "Id": "Eyes"
          }
        },
        "Videos": [],
        "Pros": null,
        "SecondaryRatings": {},
        "ClientResponses": [],
        "Photos": [],
        "Cons": null,
        "IsSyndicated": false,
        "SecondaryRatingsOrder": [],
        "AdditionalFields": {},
        "RatingRange": {
          "$numberInt": "5"
        },
        "TagDimensions": {},
        "AdditionalFieldsOrder": [],
        "ProductRecommendationIds": [],
        "CommentIds": [],
        "TagDimensionsOrder": []
      }
    ],
    "HasErrors": false,
    "Errors": []
  },
  "name": "L'Atelier des Subtils Eau d'Océan - Eau de toilette",
}

I was thinking of a cause like making a find_all with:

users = ['Jackobear']
collection.findall({'q2.Results.x.UserNickname' : {'$in': users}})

If it is not possible, I suppose I have to make a new database with the perfumes appreciated by each person? How can I make the script that could retrieve this information from the database by searching these documents for each user?

I tried Daniel's response:

def collaborative_recommendation(users, k):
    # je veux tous les items que l'utilisateur a liké
    list(collection.aggregate([
        { $project:{
            "q2.Results":{ $filter:{
                input: "q2.Results",
                as:"resultado",
                cond: {$eq: ["$$resultado.UserNickname", users]}
            }}
        }}
    ]))
    # et on fait une recommendation par user
    return None

I also use Python, but it seems that Python has problems to understand this. In effect I get:

OperationFailure at /recommend/
input to $filter must be an array not string, full error: {'operationTime': Timestamp(1620134892, 3), 'ok': 0.0, 'errmsg': 'input to $filter must be an array not string', 'code': 28651, 'codeName': 'Location28651', '$clusterTime': {'clusterTime': Timestamp(1620134892, 3), 'signature': {'hash': b'?\xf6\xff\xfe\x16G*<rzD\xc2B\xa5d\xf1\xfb\xea2U', 'keyId': 6914681777856446469}}}

0voto

A solution to this problem can be solved with aggregate from mongodb and we help each other with $filtet to make the solution more efficient.

db.Prueba.aggregate([
{ $match: { "_id": ObjectId("5fd5e617260828c7646000aa") } },
{ $project: {
        "q2.Results": { $filter: { 
                input: "$q2.Results",
                as: "resultado",
                cond: { $eq: [ "$$resultado.UserNickname", "Jackobear" ] }
           }
        }
    } 
}
])

Then the result shows the complete document but with the sub-documents of the Array. q2.Results whose value of UserNickname is equal to "Jackobear"

{
    "_id" : ObjectId("5fd5e617260828c7646000aa"),
    "q2" : {
        "Results" : [ 
            {
                "Id" : "163069310",
                "CID" : "eb523c23-980d-5661-b9d0-c6dc1028fa42",
                "SourceClient" : "sephora-fr",
                "Badges" : {
                    "loyaltyYes--Im-a-VIB-Rouge" : {
                        "ContentType" : "REVIEW",
                        "Id" : "loyaltyYes--Im-a-VIB-Rouge",
                        "BadgeType" : "Custom"
                    }
                },
                "BadgesOrder" : [ 
                    "loyaltyYes--Im-a-VIB-Rouge"
                ],
                "LastModeratedTime" : "2020-09-22T12:00:18.000+00:00",
                "LastModificationTime" : "2020-12-10T14:36:16.000+00:00",
                "ProductId" : "P3742199",
                "CampaignId" : "BV_PIE_ONLINE",
                "ContextDataValuesOrder" : [ 
                    "Gender", 
                    "Eyes", 
                    "Skin"
                ],
                "UserLocation" : "Paris",
                "AuthorId" : "78948942",
                "ContentLocale" : "fr_FR",
                "IsFeatured" : false,
                "TotalInappropriateFeedbackCount" : {
                    "$numberInt" : "0"
                },
                "TotalClientResponseCount" : {
                    "$numberInt" : "0"
                },
                "TotalCommentCount" : {
                    "$numberInt" : "0"
                },
                "Rating" : {
                    "$numberInt" : "5"
                },
                "IsRatingsOnly" : false,
                "IsRecommended" : true,
                "Helpfulness" : {
                    "$numberDouble" : "1.0"
                },
                "TotalFeedbackCount" : {
                    "$numberInt" : "2"
                },
                "TotalNegativeFeedbackCount" : {
                    "$numberInt" : "0"
                },
                "TotalPositiveFeedbackCount" : {
                    "$numberInt" : "2"
                },
                "ModerationStatus" : "APPROVED",
                "SubmissionId" : "r23232-fr__16007743UA3Zr3O9L5",
                "SubmissionTime" : "2020-09-22T11:32:57.000+00:00",
                "ReviewText" : "J’adore, il sent le bord de mer une ressemblance avec le parfum Kenzo",
                "Title" : "Très bon parfum",
                "UserNickname" : "Jackobear",
                "ContextDataValues" : {
                    "Gender" : {
                        "Value" : "Male",
                        "Id" : "Gender"
                    },
                    "Skin" : {
                        "Value" : "Normale",
                        "Id" : "Skin"
                    },
                    "Eyes" : {
                        "Value" : "Marrons",
                        "Id" : "Eyes"
                    }
                },
                "Videos" : [],
                "Pros" : null,
                "InappropriateFeedbackList" : [],
                "SecondaryRatings" : {},
                "ClientResponses" : [],
                "Photos" : [],
                "Cons" : null,
                "IsSyndicated" : false,
                "SecondaryRatingsOrder" : [],
                "AdditionalFields" : {},
                "RatingRange" : {
                    "$numberInt" : "5"
                },
                "TagDimensions" : {},
                "AdditionalFieldsOrder" : [],
                "ProductRecommendationIds" : [],
                "CommentIds" : [],
                "TagDimensionsOrder" : []
            }
        ]
    }
}

HolaDevs.com

HolaDevs is an online community of programmers and software lovers.
You can check other people responses or create a new question if you don't find a solution

Powered by:

X