1

I am trying to make a pretty simple mongoDB document to track searches by date in a node.js project. Here's what I'm shooting for:

{
"date": 1626930000000,
"searches": [
            {
             "search": "search 1",
             "count": 2
            },
            {
             "search": "search 2",
             "count": 5
            }
          ]
}

I want to update/add new searches to each date and increment the count for existing searches. Then on new dates do the same thing. Here is my current attempt using mongoose:

const query = { date: date, searches: { search: search } };
        guideSearchesModel.findOneAndUpdate(query, {$addToSet: { searches: search ,$inc: { count: 1 }}}, { upsert: true, new: true }, callback);

But this is what gets added to the DB:

{
  "_id": {
    "$oid": "60f9eb370f12712140dd29db"
  },
  "date": 1626930000000,
  "searches": {
    "_id": {
      "$oid": "60f9eb38c4ff591f50137726"
    },
    "search": "search 1"
  }

Its missing the "count", and if I run it again it inserts a new document, doesn't update the one I want to based on the date.

Any ideas would be greatly appreciated.

Thanks!

Orcinus
  • 11
  • 2
  • To update a specific matching array element use the update option [$arrayFIlters](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#update-specific-elements-of-an-array-of-documents). – prasad_ Jul 23 '21 at 00:24
  • Maybe have a look on `upsert` - it creates a field if is doesn't exist already -> https://stackoverflow.com/questions/2801008/mongodb-insert-if-not-exists – AutMai Jul 23 '21 at 07:43

1 Answers1

0

The query {searches: {search: "search 1"}} is an exact document search, meaning it will match a document that contains a field named searches that contains an object with exactly 1 field named search with the value "search 1". i.e. it will not match those sample documents, and therefore it will always upsert.

To match fields in subdocuments, use dotted notation, like

{"searches.search": "search 1"}

Also note that the query part of that update matches both a date and the search object, which means if a document exists in the collection with the desired date, but doesn't contain the search in its array, a new document with the date will be inserted.

It looks like you want to conditionally update the document by appending the search to the array if it doesn't exist, and incrementing its count if it does. This will require you to use the aggregation pipeline form of the update command, like Update MongoDB field using value of another field.

Joe
  • 25,000
  • 3
  • 22
  • 44