[SERVER-31702] String padding functionality Created: 24/Oct/17  Updated: 06/Dec/22

Status: Backlog
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: Kaitlin Mahar Assignee: Backlog - Query Optimization
Resolution: Unresolved Votes: 1
Labels: expression
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
Assigned Teams:
Query Optimization
Participants:

 Description   

It would be useful to have some operator to pad strings to specified lengths



 Comments   
Comment by Asya Kamsky [ 24/Jan/20 ]

jacek.s.gajek@gmail.com I created the function in Javascript because I ran it in mongo shell. You would want to create a local method that generated an appropriate pipeline. In other words, that function should be local to your code and generate the pipeline you then pass to aggregate command.

Comment by Jacek Gajek [ 24/Jan/20 ]

@Asya.kamsky

How to access it by Java/Kotlin driver? I'd like to return a sorted list of documents, using a padded with ze1roes string as a sort key. I tried:

mongoDb.runCommand(Document.parse("" +
        "\n" +
      "lpad = function (str, len, padstr=\" \") {\n" +
       "     var redExpr={\$reduce:{input:{\$range:[0,{\$subtract:[len, {\$strLenCP:str}]}]}, initialValue:\"\", in:{\$concat:[\"\\$\$value\",padstr]}}};\n" +
      "     return {\$cond:{if:{\$gte:[{\$strLenCP:str},len]}, then:str, else:{\$concat:[ redExpr, str]}}}; \n" +
 "}"))
 
 
col.aggregate(mutableListOf(
 Aggregates.addFields(Field("refint", """lpad("${"$"}ref", 10,"0" }""")),
 Aggregates.sort(Sorts.ascending("refint"))
 ))

Obviously it fails in the first stepbecause lpad=function(...) is not a valid JSON, but I have no idea how to do it in other way. Also, is the second step correct even assuming that a function already exist? (although it does not)

Comment by Asya Kamsky [ 26/Oct/17 ]

You can already achieve it with existing aggregation expressions:

lpad = function (str, len, padstr=" ") {
     var redExpr={$reduce:{input:{$range:[0,{$subtract:[len, {$strLenCP:str}]}]}, initialValue:"", in:{$concat:["$$value",padstr]}}};
     return {$cond:{if:{$gte:[{$strLenCP:str},len]}, then:str, else:{$concat:[ redExpr, str]}}}; 
}
lpad("$string", 20, "x")
{
	"$cond" : {
		"if" : {
			"$gte" : [
				{
					"$strLenCP" : "$string"
				},
				20
			]
		},
		"then" : "$string",
		"else" : {
			"$concat" : [
				{
					"$reduce" : {
						"input" : {
							"$range" : [
								0,
								{
									"$subtract" : [
										20,
										{
											"$strLenCP" : "$string"
										}
									]
								}
							]
						},
						"initialValue" : "",
						"in" : {
							"$concat" : [
								"$$value",
								"x"
							]
						}
					}
				},
				"$string"
			]
		}
	}
}

With sample data:

db.strings.find()
{ "_id" : ObjectId("59f2107bf8e2fe24ca29dd80"), "a" : "xxx" }
{ "_id" : ObjectId("59f2107ff8e2fe24ca29dd81"), "a" : "yyyyyy" }
{ "_id" : ObjectId("59f21083f8e2fe24ca29dd82"), "a" : "zzzzzzzzz" }
db.strings.aggregate({$project:{_id:0, paddedA:lpad("$a",10)}})
{ "paddedA" : "       xxx" }
{ "paddedA" : "    yyyyyy" }
{ "paddedA" : " zzzzzzzzz" }

Generated at Thu Feb 08 04:27:56 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.