[{"data":1,"prerenderedAt":797},["ShallowReactive",2],{"Categories":3,"NavIndexCategoriesCountFooter":203,"content-\u002F2014\u002F05\u002F02\u002Fpostgresql-sort-where-id-in-by-original-id-list-order\u002F":204},[4,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,70,71,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202],{"category":5},"System Administration",{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},"Software Development",{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":27},{"category":27},{"category":67},"Drones & RC",{"category":69},"DIY Projects",{"category":67},{"category":72},"Photography",{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":67},{"category":67},{"category":72},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":5},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":67},{"category":67},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":72},{"category":67},{"category":138},"3D Printing - Laser Cutting - CNC",{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":5},{"category":138},{"category":27},{"category":27},{"category":138},{"category":138},{"category":72},{"category":158},"Photography,3D Printing - Laser Cutting - CNC",{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":67},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":181},"Home Assistant",{"category":181},{"category":72},{"category":27},{"category":27},{"category":72},{"category":138},{"category":5},{"category":72},{"category":72},{"category":138},{"category":27},{"category":181},{"category":181},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},191,{"id":205,"title":206,"body":207,"category":784,"date":785,"description":786,"embedImage":784,"extension":787,"image":784,"intro":784,"meta":788,"navigation":604,"path":789,"seo":790,"series":784,"sitemap":791,"stem":792,"tags":793,"__hash__":796},"content\u002F2014\u002F05\u002F02\u002Fpostgresql-sort-where-id-in-by-original-id-list-order.md","Postgresql sort 'WHERE id IN' by original id list order",{"type":208,"value":209,"toc":782},"minimark",[210,225,228,264,267,270,342,345,353,356,529,532,727,730,770,778],[211,212,213,214,224],"p",{},"I've been testing ",[215,216,223],"a",{"href":217,"rel":218,"target":222},"http:\u002F\u002Fwww.elasticsearch.org\u002F",[219,220,221],"nofollow","noopener","noreferer","_blank","elasticsearch"," in a rails project recently - and stumbled on an issue with sorting.",[211,226,227],{},"You see - elasticsearch returns the search results either sorted by score or by the sort order you ask for. Then you need to convert the search results to records - so a simple",[229,230,235],"pre",{"className":231,"code":232,"language":233,"meta":234,"style":234},"language-ruby shiki shiki-themes github-dark","ModelType.where(id: ids)\n","ruby","",[236,237,238],"code",{"__ignoreMap":234},[239,240,243,247,251,255,258,261],"span",{"class":241,"line":242},"line",1,[239,244,246],{"class":245},"sDLfK","ModelType",[239,248,250],{"class":249},"s95oV",".",[239,252,254],{"class":253},"svObZ","where",[239,256,257],{"class":249},"(",[239,259,260],{"class":245},"id:",[239,262,263],{"class":249}," ids)\n",[211,265,266],{},"However - on postgresql - this returns the records in database order (seems to be insert order).",[211,268,269],{},"You could try sorting post fetch:",[229,271,273],{"className":231,"code":272,"language":233,"meta":234,"style":234},"index = ModelType.where(id: ids).to_a.group_by(&:id)\nids.map { |i| index[i.to_i].first }\n",[236,274,275,318],{"__ignoreMap":234},[239,276,277,281,285,288,290,292,294,296,299,302,304,307,309,312,315],{"class":241,"line":242},[239,278,280],{"class":279},"s9osk","index",[239,282,284],{"class":283},"snl16"," =",[239,286,287],{"class":245}," ModelType",[239,289,250],{"class":249},[239,291,254],{"class":253},[239,293,257],{"class":249},[239,295,260],{"class":245},[239,297,298],{"class":249}," ids).",[239,300,301],{"class":253},"to_a",[239,303,250],{"class":249},[239,305,306],{"class":253},"group_by",[239,308,257],{"class":249},[239,310,311],{"class":283},"&",[239,313,314],{"class":245},":id",[239,316,317],{"class":249},")\n",[239,319,321,324,327,330,333,336,339],{"class":241,"line":320},2,[239,322,323],{"class":249},"ids.",[239,325,326],{"class":253},"map",[239,328,329],{"class":249}," { |i| index[i.",[239,331,332],{"class":253},"to_i",[239,334,335],{"class":249},"].",[239,337,338],{"class":253},"first",[239,340,341],{"class":249}," }\n",[211,343,344],{},"But - what if we want to do this in the database.",[211,346,347,348],{},"A google search led me to ",[215,349,352],{"href":350,"rel":351,"target":222},"http:\u002F\u002Fomarqureshi.net\u002Farticles\u002F2010-6-10-find-in-set-for-postgresql",[219,220,221],"this article on how to give postgresql a similar function to mysql's find_in_set",[211,354,355],{},"So - adding a rails migration to add the function:",[229,357,361],{"className":358,"code":359,"language":360,"meta":234,"style":234},"language-sql shiki shiki-themes github-dark","create or replace function find_in_array(\n  needle anyelement, haystack anyarray) returns integer as $$\ndeclare\n  i integer;\nbegin\n  for i in 1..array_upper(haystack, 1) loop\n    if haystack[i] = needle then\n      return i;\n    end if;\n  end loop;\n  raise exception 'find_in_array: % not found in %', needle, haystack;\nend;\n$$ language 'plpgsql';\n","sql",[236,362,363,377,394,400,412,418,445,463,472,483,494,507,515],{"__ignoreMap":234},[239,364,365,368,371,374],{"class":241,"line":242},[239,366,367],{"class":283},"create or replace",[239,369,370],{"class":283}," function",[239,372,373],{"class":253}," find_in_array",[239,375,376],{"class":249},"(\n",[239,378,379,382,385,388,391],{"class":241,"line":320},[239,380,381],{"class":249},"  needle anyelement, haystack anyarray) ",[239,383,384],{"class":283},"returns",[239,386,387],{"class":283}," integer",[239,389,390],{"class":283}," as",[239,392,393],{"class":249}," $$\n",[239,395,397],{"class":241,"line":396},3,[239,398,399],{"class":283},"declare\n",[239,401,403,406,409],{"class":241,"line":402},4,[239,404,405],{"class":249},"  i ",[239,407,408],{"class":283},"integer",[239,410,411],{"class":249},";\n",[239,413,415],{"class":241,"line":414},5,[239,416,417],{"class":283},"begin\n",[239,419,421,424,427,430,433,436,439,442],{"class":241,"line":420},6,[239,422,423],{"class":283},"  for",[239,425,426],{"class":249}," i ",[239,428,429],{"class":283},"in",[239,431,432],{"class":245}," 1",[239,434,435],{"class":249},"..array_upper(haystack, ",[239,437,438],{"class":245},"1",[239,440,441],{"class":249},") ",[239,443,444],{"class":283},"loop\n",[239,446,448,451,454,457,460],{"class":241,"line":447},7,[239,449,450],{"class":283},"    if",[239,452,453],{"class":249}," haystack[i] ",[239,455,456],{"class":283},"=",[239,458,459],{"class":249}," needle ",[239,461,462],{"class":283},"then\n",[239,464,466,469],{"class":241,"line":465},8,[239,467,468],{"class":283},"      return",[239,470,471],{"class":249}," i;\n",[239,473,475,478,481],{"class":241,"line":474},9,[239,476,477],{"class":283},"    end",[239,479,480],{"class":283}," if",[239,482,411],{"class":249},[239,484,486,489,492],{"class":241,"line":485},10,[239,487,488],{"class":283},"  end",[239,490,491],{"class":283}," loop",[239,493,411],{"class":249},[239,495,497,500,504],{"class":241,"line":496},11,[239,498,499],{"class":249},"  raise exception ",[239,501,503],{"class":502},"sU2Wk","'find_in_array: % not found in %'",[239,505,506],{"class":249},", needle, haystack;\n",[239,508,510,513],{"class":241,"line":509},12,[239,511,512],{"class":283},"end",[239,514,411],{"class":249},[239,516,518,521,524,527],{"class":241,"line":517},13,[239,519,520],{"class":249},"$$ ",[239,522,523],{"class":283},"language",[239,525,526],{"class":502}," 'plpgsql'",[239,528,411],{"class":249},[211,530,531],{},"and an initializer file where we override:",[229,533,535],{"className":231,"code":534,"language":233,"meta":234,"style":234},"class String\n  def sql_escape\n    self.gsub(\u002F[%_'\\\\\"]\u002F, \"\\\\\\\\\\\\0\")\n  end\nend\n\nclass Array\n  def to_postgres_array\n    \"'{\" + self.inject([]) do |mem, val|\n      mem \u003C\u003C (val.kind_of?(String) ? \"\\\"#{val.sql_escape}\\\"\" : val)\n      mem\n    end.join(\", \") + \"}'\"\n  end\nend\n",[236,536,537,545,553,590,595,600,606,613,620,645,691,696,718,722],{"__ignoreMap":234},[239,538,539,542],{"class":241,"line":242},[239,540,541],{"class":283},"class",[239,543,544],{"class":253}," String\n",[239,546,547,550],{"class":241,"line":320},[239,548,549],{"class":283},"  def",[239,551,552],{"class":253}," sql_escape\n",[239,554,555,558,560,563,565,569,573,576,579,582,585,588],{"class":241,"line":396},[239,556,557],{"class":245},"    self",[239,559,250],{"class":249},[239,561,562],{"class":245},"gsub",[239,564,257],{"class":249},[239,566,568],{"class":567},"sns5M","\u002F[%_'",[239,570,572],{"class":571},"sRjNt","\\\\",[239,574,575],{"class":567},"\"]\u002F",[239,577,578],{"class":249},", ",[239,580,581],{"class":502},"\"",[239,583,584],{"class":245},"\\\\\\\\\\\\",[239,586,587],{"class":502},"0\"",[239,589,317],{"class":249},[239,591,592],{"class":241,"line":402},[239,593,594],{"class":283},"  end\n",[239,596,597],{"class":241,"line":414},[239,598,599],{"class":283},"end\n",[239,601,602],{"class":241,"line":420},[239,603,605],{"emptyLinePlaceholder":604},true,"\n",[239,607,608,610],{"class":241,"line":447},[239,609,541],{"class":283},[239,611,612],{"class":253}," Array\n",[239,614,615,617],{"class":241,"line":465},[239,616,549],{"class":283},[239,618,619],{"class":253}," to_postgres_array\n",[239,621,622,625,628,631,633,636,639,642],{"class":241,"line":474},[239,623,624],{"class":502},"    \"'{\"",[239,626,627],{"class":283}," +",[239,629,630],{"class":245}," self",[239,632,250],{"class":249},[239,634,635],{"class":253},"inject",[239,637,638],{"class":249},"([]) ",[239,640,641],{"class":283},"do",[239,643,644],{"class":249}," |mem, val|\n",[239,646,647,650,653,656,659,661,664,666,669,672,675,678,681,684,686,688],{"class":241,"line":485},[239,648,649],{"class":249},"      mem ",[239,651,652],{"class":283},"\u003C\u003C",[239,654,655],{"class":249}," (val.",[239,657,658],{"class":253},"kind_of?",[239,660,257],{"class":249},[239,662,663],{"class":245},"String",[239,665,441],{"class":249},[239,667,668],{"class":283},"?",[239,670,671],{"class":502}," \"",[239,673,674],{"class":245},"\\\"",[239,676,677],{"class":502},"#{val.",[239,679,680],{"class":253},"sql_escape",[239,682,683],{"class":502},"}",[239,685,674],{"class":245},[239,687,581],{"class":502},[239,689,690],{"class":249}," : val)\n",[239,692,693],{"class":241,"line":496},[239,694,695],{"class":249},"      mem\n",[239,697,698,700,702,705,707,710,712,715],{"class":241,"line":509},[239,699,477],{"class":283},[239,701,250],{"class":249},[239,703,704],{"class":253},"join",[239,706,257],{"class":249},[239,708,709],{"class":502},"\", \"",[239,711,441],{"class":249},[239,713,714],{"class":283},"+",[239,716,717],{"class":502}," \"}'\"\n",[239,719,720],{"class":241,"line":517},[239,721,594],{"class":283},[239,723,725],{"class":241,"line":724},14,[239,726,599],{"class":283},[211,728,729],{},"We end up able to call:",[229,731,733],{"className":231,"code":732,"language":233,"meta":234,"style":234},"ModelType.where(id: ids).order(\"find_in_array(id, #{ids.to_postgres_array})\")\n",[236,734,735],{"__ignoreMap":234},[239,736,737,739,741,743,745,747,749,752,754,757,760,763,765,768],{"class":241,"line":242},[239,738,246],{"class":245},[239,740,250],{"class":249},[239,742,254],{"class":253},[239,744,257],{"class":249},[239,746,260],{"class":245},[239,748,298],{"class":249},[239,750,751],{"class":253},"order",[239,753,257],{"class":249},[239,755,756],{"class":502},"\"find_in_array(id, ",[239,758,759],{"class":502},"#{ids.",[239,761,762],{"class":253},"to_postgres_array",[239,764,683],{"class":502},[239,766,767],{"class":502},")\"",[239,769,317],{"class":249},[211,771,772,773,777],{},"Benchmarking this on my small'ish dataset shows that this ",[774,775,776],"em",{},"is"," faster than the post fetch sort in ruby. Not sure what it does on larger data sets though.",[779,780,781],"style",{},"html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sns5M, html code.shiki .sns5M{--shiki-default:#DBEDFF}html pre.shiki code .sRjNt, html code.shiki .sRjNt{--shiki-default:#85E89D;--shiki-default-font-weight:bold}",{"title":234,"searchDepth":320,"depth":320,"links":783},[],null,"2014-05-02 10:36 +0200","I've been testing elasticsearch in a rails project recently - and stumbled on an issue with sorting.","md",{},"\u002F2014\u002F05\u002F02\u002Fpostgresql-sort-where-id-in-by-original-id-list-order",{"title":206,"description":786},{"loc":789},"2014\u002F05\u002F02\u002Fpostgresql-sort-where-id-in-by-original-id-list-order",[794,795],"postgresql","rails","WCbnX5nF9PbS1pxykDqcb_5ZBOBtVtm9j7vWgfZFepE",1775293010969]