Удалить https / https из документов данных mongodb - PullRequest
2 голосов
/ 10 октября 2019

Как удалить http:// или https:// с начала и '/' с конца tags.Domain в агрегации MongoDB?

Образец документа:

{
    "_id" : ObjectId("5d9f074f5833c8cd1f685e05"),
    "tags" : [
        {
            "Domain" : "http://www.google.com",
            "rank" : 1
        },
        {
            "Domain" : "https://www.stackoverflow.com/",
            "rank" : 2
        }
    ]
}

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Предполагая, что поле Домен в тегах будет содержать действительные URL-адреса с допустимыми добавлениями и добавлениями (https, http, //, /, com /,org /, / in)

  • Оператор $ trim используется для удаления https://, http:// и /от tags.Domain

ПРИМЕЧАНИЕ: Это не будет работать для URL, который уже отформатирован и не содержит этих символов в начале / конце. Пример: 'hello.com' would become 'ello.com', 'xyz.ins' would become 'xyz.in' и т. Д.

Запрос агрегации :

db.collection.aggregate([
  {
    $addFields:{
      "tags":{
        $map:{
          "input":"$tags",
          "as":"tag",
          "in":{
            $mergeObjects:[
              "$$tag",
              {
                "Domain":{ 
                  $trim: { 
                    "input": "$$tag.Domain", 
                    "chars": "https://" 
                  } 
                }
              }
            ]
          }
        }
      }
    }
  }    
]).pretty()

Выход: (демо)

{
        "_id" : 2, //ObjectId
        "tags" : [
                {
                        "rank" : 1,
                        "Domain" : "www.google.com"
                },
                {
                        "rank" : 2,
                        "Domain" : "www.stackoverflow.com"
                }
        ]
}
1 голос
/ 10 октября 2019

Решение оказалось длиннее, чем я ожидал (я надеюсь, что кто-то найдет более краткое решение), но вы идете:

db.test.aggregate([
{$unwind:"$tags"}, //unwind tags so that we can separately deal with http and https
{
    $facet: { 
        "https": [{ // the first stage will...
            $match: { // only contain documents...
                "tags.Domain": /^https.*/ // that are allowed by the match the regex /^https.*/
            }
        }, {
            $addFields: { // for all matching documents...
                "tags.Domain": {"$substr": ["$tags.Domain",8,-1]} // we change the tags.Domain field to required substring (skip 8 characters and go on till the last character)
            }
        }],
        "http": [{ // similar as above except we're doing the inverse filter using $not
            $match: {
                "tags.Domain": { $not: /^https.*/ }
            }
        }, {
            $addFields: { // for all matching documents...
                "tags.Domain": {"$substr": ["$tags.Domain",7,-1]} // we change the tags.Domain field to required substring (skip 7 characters and go on till the last character)
            }
        }
        ]
    }
},

{ $project: { all: { $concatArrays: [ "$https", "$http" ] } } }, //we have two arrays at this point, so we just concatenate them both to have one array called "all"

//unwind and group the array by _id to get the document back in the original format

{$unwind: "$all"}, 

{$group: {
        _id: "$all._id",
        tags: {$push: "$all.tags"}
}}
])

Для удаления / с конца выможет иметь другой фасет с регулярным выражением, совпадающим с URL (что-то вроде /.*\/$/ должно работать), и использовать этот фасет также в concat.

С помощью: https://stackoverflow.com/a/49660098/5530229 и https://stackoverflow.com/a/44729563/5530229

Как сказал dnickless в первом ответе, упомянутом выше, , как всегда в структуре агрегации, это может помочьудалите отдельные этапы из конца конвейера и выполните частичный запрос, чтобы понять, что делает каждый отдельный этап.

...