এফটিএস বিন্দু সহ ইমেলগুলির সাথে প্রত্যাশার মতো কাজ করে না


9

আমরা একটি বৃহত সিস্টেমের অংশ হিসাবে একটি অনুসন্ধান বিকাশ করছি।

আমাদের Microsoft SQL Server 2014 - 12.0.2000.8 (X64) Standard Edition (64-bit)এই সেটআপটি রয়েছে:

CREATE TABLE NewCompanies(
    [Id] [uniqueidentifier] NOT NULL,
    [Name] [nvarchar](400) NOT NULL,
    [Phone] [nvarchar](max) NULL,
    [Email] [nvarchar](max) NULL,
    [Contacts1] [nvarchar](max) NULL,
    [Contacts2] [nvarchar](max) NULL,
    [Contacts3] [nvarchar](max) NULL,
    [Contacts4] [nvarchar](max) NULL,
    [Address] [nvarchar](max) NULL,
    CONSTRAINT PK_Id PRIMARY KEY (Id)
);
  1. Phone স্ট্রাকচার্ড কমা দ্বারা বিভাজিত অঙ্কগুলির মতো স্ট্রিং "77777777777, 88888888888"
  2. Emailকাঠামোগত ইমেলের মতো স্ট্রাকচারযুক্ত "email1@gmail.com, email2@gmail.com"( যেমন কমা বা বিনাভাবে "email1@gmail.com")
  3. Contacts1, Contacts2, Contacts3, Contacts4ব্যবহারকারীরা নিখরচায় যোগাযোগের বিশদ নির্দিষ্ট করতে পারে এমন পাঠ্য ক্ষেত্র are লাইক "John Smith +1 202 555 0156"বা "Bob, +1-999-888-0156, bob@company.com"। এই ক্ষেত্রগুলিতে ইমেল এবং ফোন থাকতে পারে আমরা আরও অনুসন্ধান করতে চাই।

এখানে আমরা পূর্ণ-পাঠ্য সামগ্রী তৈরি করি

-- FULL TEXT SEARCH
CREATE FULLTEXT CATALOG NewCompanySearch AS DEFAULT;  
CREATE FULLTEXT INDEX ON NewCompanies(Name, Phone, Email, Contacts1, Contacts2, Contacts3, Contacts4, Address)
KEY INDEX PK_Id

এখানে একটি তথ্য নমুনা

INSERT INTO NewCompanies(Id, Name, Phone, Email, Contacts1, Contacts2, Contacts3, Contacts4) 
VALUES ('7BA05F18-1337-4AFB-80D9-00001A777E4F', 'PJSC Azimuth', '79001002030, 78005005044', 'regular@hotmail.com, s.m.s@gmail.com', 'John Smith', 'Call only at weekends +7-999-666-22-11', NULL, NULL)

আসলে আমাদের কাছে প্রায় 100 হাজার রেকর্ড রয়েছে।

আমরা প্রত্যাশা করি যে ব্যবহারকারীরা "@ gmail.com" এর মতো ইমেলের একটি অংশ নির্দিষ্ট করতে পারবেন এবং এটি যে কোনও Email, Contacts1, Contacts2, Contacts3, Contacts4ক্ষেত্রেই জিমেইল ইমেল ঠিকানা সহ সমস্ত সারি ফিরিয়ে আনবে।

ফোন নম্বরগুলির জন্য একই। ব্যবহারকারীরা "70283" এর মতো কোনও প্যাটার্ন অনুসন্ধান করতে পারেন এবং কোনও প্রশ্নের মধ্যে এই অঙ্কগুলির সাথে ফোনগুলি ফিরতে হবে। এটি এমনকি ফর্ম ফর্ম Contacts1, Contacts2, Contacts3, Contacts4ক্ষেত্রগুলির জন্য যেখানে আমাদের সম্ভবত অনুসন্ধানের আগে প্রথমে অঙ্কগুলি এবং স্পেস অক্ষরগুলি বাদ দেওয়া উচিত।

আমরা LIKEপ্রায় 1500 টি রেকর্ড থাকাকালীন অনুসন্ধানের জন্য ব্যবহার করতাম এবং এটি দুর্দান্ত কাজ করে তবে এখন আমাদের অনেক রেকর্ড রয়েছে এবং LIKEঅনুসন্ধানে ফলাফল পেতে অসীম লাগে।

আমরা সেখান থেকে ডেটা পাওয়ার চেষ্টা করি:

SELECT * FROM NewCompanies WHERE CONTAINS((Email, Contacts1, Contacts2, Contacts3, Contacts4), '"s.m.s@gmail.com*"') -- this doesn't get the row
SELECT * FROM NewCompanies WHERE CONTAINS((Phone, Contacts1, Contacts2, Contacts3, Contacts4), '"6662211*"') -- doesn't get anything
SELECT * FROM NewCompanies WHERE CONTAINS(Name, '"zimuth*"') -- doesn't get anything

5
আপনার সমস্ত কলাম nvarchar(MAX)এখানে কেন ? যার নাম 1 বিলিয়ন ~ অক্ষর লম্বা তা আমি কখনও শুনিনি বা সাক্ষাত করি নি। এবং, এই উত্তর অনুসারে , একটি ইমেল ঠিকানা 254 অক্ষরের বেশি হতে পারে না; সুতরাং আপনার সেখানে 1 বিলিয়ন ডলার নষ্ট অক্ষর রয়েছে।
লার্নু

2
আপনি পুরো-পাঠ্যের অনুসন্ধানের শব্দ ভঙ্গকারীদের সাথে লড়াইয়ের মতো শোনাচ্ছেন। আপনি @gmail.comঅনুসন্ধান শব্দ হিসাবে কোনও কিছুই খুঁজে পাওয়ার সম্ভাবনা নেই কারণ @চরিত্রটি একটি শব্দ বিভাজক। অন্য কথায়, আপনার আছে SQL সার্ভার সংস্করণ নির্ভর সালে সূচক শব্দের জন্য user@gmail.comপারেন (একটি) হতে হবে user, gmailএবং comবা (খ) user, user@gmail.com, gmailএবং com। REF: সম্পূর্ণ পাঠ্য অনুসন্ধানে আচরণগত পরিবর্তন
সর্বদা

1
"তবে আমি সেই ক্ষেত্রগুলিতে ইমেল এবং ফোনগুলি ছাড়া আর কোনও কিছু অনুসন্ধান করতে চাই না" তবে সেগুলি একটি উপযুক্ত কলামে সংরক্ষণ করা উচিত, যেমনটি আমি আগে বলেছিলাম। আপনার কাছে সেই ডেটাটির জন্য কলাম রয়েছে, যা সাধারণ হওয়া উচিত। শব্দ ভঙ্গকারীদের উদাহরণ / ডাটাবেস স্তরে সেট করা আছে। সুতরাং এটি মুছে ফেলার জন্য একটি গুরুত্বপূর্ণ ব্রেকিং পরিবর্তন হবে .
লার্নু

1
আপনি সমস্ত ফোন, ইমেল ইত্যাদি রেকর্ডগুলির জন্য টেবিলগুলি 1-এম তে স্বাভাবিক করতে চান দ্বিতীয় বিকল্পটি কলামগুলি বিভক্ত করা (স্ট্রিং_স্প্লিট (ইমেল, ',') আউটর অ্যাপ্লিকেশনের সাথে মিশ্রিত করতে হবে to ব্যবহারকারীর কাছে থাকতে পারে এমন ইমেলগুলির সংখ্যার উপর একটি তাত্ত্বিক সীমা উল্লেখ করুন তারপরে একটি অনুসন্ধান লিখুন: SELECT * FROM NewCompanies WHERE Id IN (SELECT ID from .... where MyOuterApply.EmailCol1 LIKE '%'+@SearchString+'%') OR Id IN (SELECT ID from .... where MyOuterApply.EmailCol2 LIKE '%'+@SearchString+'%')প্রতিটি ক্ষেত্রে প্রায় পাঁচটি পৃথক সূচক তৈরি করুন এবং প্রাথমিক কীটি অন্তর্ভুক্ত করুন
স্টারবোন

2
পুনঃটুইট করেছেন ওপিরা যে কারণে সমস্যাটি নিয়ে আসছেন তা হ'ল সাধারণীকরণের অভাব।
লার্নু

উত্তর:


2

আসলে অনুরোধ

নির্বাচন করুন [...] যোগাযোগ ([...], '"6662211 *"') - কিছুই পান না

বিরুদ্ধে 'Call only at weekends +7-999-666-22-11' এবং

নির্বাচন করুন [...] বিষয়বস্তু (নাম, '"জিমুথ *"') - কিছুই পান না

বিরুদ্ধে 'PJSC Azimuth'

কি আশানুরূপ কাজউপসর্গের টার্মটি
দেখুন । কারণ নয় হয় উপসর্গ এর সেইসাথে একটি না প্রিফিক্স এর6662211*+7-999-666-22-11zimuth*Azimuth

জন্য

নির্বাচন করুন [...] যোগাযোগগুলি ([...], '"sms@gmail.com*")) - এটি সারিটি পায় না

এটি সম্ভবত শব্দ ভঙ্গকারীদের কারণ হিসাবে সর্বদা মন্তব্যে নির্দেশিত হয়েছে। দেখুন শব্দ-ভঙ্গকারী

আমি মনে করি না যে সম্পূর্ণ-পাঠ্য অনুসন্ধান আপনার কাজের জন্য প্রযোজ্য।

LIKE অপারেটর যে একই কাজের জন্য ব্যবহৃত হয় ঠিক সেই একই কাজে FTS- এর ব্যবহার কেন? LIKE ক্যোয়ারির জন্য যদি আরও ভাল সূচী টাইপ থাকে ... তবে আরও ভাল সূচক প্রকারটি হত , সম্পূর্ণ আলাদা প্রযুক্তি এবং বাক্য গঠন নয়।
এবং কোনও উপায়েই এটি আপনাকে "6662211*""666 কিছু স্বেচ্ছাচারী চর 22 কিছু স্বেচ্ছাচারী চর 11" এর সাথে মিলতে সহায়তা করবে না ।
সম্পূর্ণ পাঠ্য অনুসন্ধানটি রেজেক্স-এস সম্পর্কিত নয় (এবং "6662211*"কাজের জন্য এটি সঠিক ধারণাও নয় - "কিছু স্বেচ্ছাচারী চর" অংশ সম্পর্কে কিছুই নেই) এটি প্রতিশব্দ, শব্দের ফর্ম ইত্যাদি সম্পর্কে about

তবে সাবস্ট্রিংগুলি কার্যকরভাবে অনুসন্ধান করা কি আদৌ সম্ভব?

হ্যাঁ তাই হয়। আপনার নিজস্ব অনুসন্ধান ইঞ্জিন লেখার মতো সম্ভাবনাগুলি বাদ দিয়ে আমরা এর মধ্যে কী করতে পারি SQL?

প্রথমত - আপনার ডেটা সাফ করা জরুরি! আপনি যদি ব্যবহারকারীদের কাছে ঠিক মতো স্ট্রিং প্রবেশ করিয়ে দিতে চান তবে

ব্যবহারকারীরা ফর্ম ফর্ম যোগাযোগের বিবরণ নির্দিষ্ট করতে পারেন

... আপনি তাদেরকে যেমন আছে তেমন সংরক্ষণ করতে পারেন ... এবং এগুলি রেখে যান leave
তারপর আপনি প্রয়োজন নিষ্কর্ষ বিনামূল্যে ফর্ম লেখা থেকে তথ্য এবং কিছু ক্যানোনিকাল ফর্ম ডেটা সংরক্ষণ (এটা খুব একটা কঠিন ইমেল এবং ফোন নম্বর জন্য নয়)। ইমেলের জন্য, কেবলমাত্র আপনাকে যা করতে হবে তা হ'ল - এগুলি সমস্ত ছোট ছোট বা বড় হাতের অক্ষরে তৈরি করুন (কোনও ব্যাপার নয়), এবং সম্ভবত @গানে বিভাজন । তবে ফোন নম্বরগুলিতে আপনাকে কেবল অঙ্কগুলি রেখে যেতে হবে
(... এবং তারপরে আপনি এগুলি সংখ্যা হিসাবে সংরক্ষণও করতে পারেন That এটি আপনাকে কিছু জায়গা এবং সময় সাশ্রয় করতে পারে But তবে অনুসন্ধানটি আলাদা হবে ... আপাতত আরও সহজ করে নেব এবং স্ট্রিং ব্যবহার করে সর্বজনীন সমাধান

ম্যাথুবেকার যেমন উল্লেখ করেছেন আপনি প্রত্যয়ের টেবিল তৈরি করতে পারেন। তাহলে আপনিও এর মতো অনুসন্ধান করতে পারেন

SELECT DISTINCT * FROM NewCompanies JOIN Sufficies ON NewCompanies.Id = Sufficies.Id WHERE Sufficies.sufficies LIKE 'some text%'

%আপনার শেষের দিকে ওয়াইল্ডকার্ড রাখা উচিত । অথবা প্রত্যয় টেবিল থেকে কোনও সুবিধা হবে না।

উদাহরণস্বরূপ একটি ফোন নম্বর নেওয়া যাক

+ + 7-999-666-22-11

আমরা এতে বর্জ্য চরগুলি পরিত্রাণ পাওয়ার পরে এটির 11 টি সংখ্যা থাকবে। এর অর্থ একটি ফোন নম্বরের জন্য আমাদের 11 টি প্রত্যয় প্রয়োজন

           1
          11
         211
        2211
       62211
      662211
     6662211
    96662211
   996662211
  9996662211
 79996662211

সুতরাং এই সমাধানের জন্য স্থান জটিলতা লিনিয়ার ... এতটা খারাপ নয়, আমি বলব ... তবে অপেক্ষা করুন এটি রেকর্ডের সংখ্যায় জটিলতা। তবে প্রতীকগুলিতে ... N(N+1)/2সমস্ত প্রত্যয় সংরক্ষণের জন্য আমাদের প্রতীক প্রয়োজন - এটি চতুর্ভুজ জটিলতা ... ভাল নয় ... তবে যদি আপনার এখন 100 000রেকর্ড থাকে এবং অদূর ভবিষ্যতে কয়েক মিলিয়ন পরিকল্পনা না রাখেন - আপনি এটি দিয়ে যেতে পারেন সমাধান।

আমরা কি স্থানের জটিলতা হ্রাস করতে পারি?

আমি কেবল ধারণাটি বর্ণনা করব, এটি বাস্তবায়নে কিছু প্রচেষ্টা নেওয়া হবে। এবং সম্ভবত আমাদের সীমা অতিক্রম করতে হবেSQL

ধরা যাক আপনার এতে 2 টি সারি এবং এতে NewCompaniesফ্রি ফর্ম পাঠ্যের 2 টি স্ট্রিং রয়েছে:

    aaaaa
    11111

প্রত্যয় টেবিলটি কত বড় হওয়া উচিত? স্পষ্টতই, আমাদের কেবল দুটি রেকর্ড দরকার।

আরেকটি উদাহরণ নেওয়া যাক। এছাড়াও 2 সারি, 2 টি নিখরচায় পাঠ্যের স্ট্রিং সন্ধান করতে। তবে এখন এটি:

    aa11aa
    cc11cc

আসুন এখন আমাদের কতগুলি প্রত্যয় প্রয়োজন তা দেখুন:

         a // no need, LIKE `a%`  will match against 'aa' and 'a11aa' and 'aa11aa'
        aa // no need, LIKE `aa%` will match against 'aa11aa'
       1aa
      11aa
     a11aa
    aa11aa
         c // no need, LIKE `c%`  will match against 'cc' and 'c11cc' and 'cc11cc'
        cc // no need, LIKE `cc%` will match against 'cc11cc'
       1cc
      11cc
     c11cc
    cc11cc

এত খারাপ না, তবে খুব ভালও নয়।

আমরা আর কি করতে পারি?

ধরা যাক, ব্যবহারকারী "c11"অনুসন্ধান ক্ষেত্রে প্রবেশ করে । তারপর LIKE 'c11%'প্রয়োজন ' C11 CC' প্রত্যয় সফল করতে। তবে যদি অনুসন্ধানের পরিবর্তে "c11"আমরা প্রথমে অনুসন্ধান করি "c%"তবে তার জন্য "c1%"এবং আরও কি? প্রথম অনুসন্ধানটি কেবলমাত্র এক সারি হিসাবে দেবে NewCompanies। এবং পরবর্তী অনুসন্ধানগুলির জন্য কোনও প্রয়োজন হবে না। এবং আমরা পারি

       1aa // drop this as well, because LIKE '1%' matches '11aa'
      11aa
     a11aa // drop this as well, because LIKE 'a%' matches 'aa11aa'
    aa11aa
       1cc // same here
      11cc
     c11cc // same here
    cc11cc

এবং আমরা কেবল 4 টি প্রত্যয় দিয়ে শেষ করি

      11aa
    aa11aa
      11cc
    cc11cc

এক্ষেত্রে স্পেস জটিলতা কী হবে তা আমি বলতে পারি না তবে এটি গ্রহণযোগ্য হবে বলে মনে হয়।


1

এই ক্ষেত্রে সম্পূর্ণ পাঠ্য সন্ধান আদর্শের চেয়ে কম। আমি যেমন ছিলাম তেমন নৌকায় ছিলাম। যেমন অনুসন্ধানগুলি খুব ধীর হয় এবং সম্পূর্ণ পাঠ্য অনুসন্ধান করে এমন শব্দের সন্ধান করে যা একটি শব্দ যুক্ত না করে একটি শব্দ দিয়ে শুরু হয়।

আমরা বেশ কয়েকটি সমাধানের চেষ্টা করেছি, একটি খাঁটি এসকিউএল বিকল্পটি হ'ল সম্পূর্ণ পাঠ্য অনুসন্ধানের নিজস্ব সংস্করণ তৈরি করা, বিশেষত একটি উল্টানো সূচক অনুসন্ধান। আমরা এটি চেষ্টা করেছিলাম, এবং এটি সফল হয়েছিল, তবে প্রচুর জায়গা নিয়েছিল। আমরা আংশিক অনুসন্ধানের পদগুলির জন্য একটি গৌণ হোল্ডিং টেবিল তৈরি করেছি এবং এতে সম্পূর্ণ পাঠ্য সূচী ব্যবহার করেছি। তবে এর অর্থ আমরা বারবার একই জিনিসটির একাধিক অনুলিপি সঞ্চয় করেছি। উদাহরণস্বরূপ আমরা "ল্যাংওয়ার্ড" লং ওয়ারওয়ার্ড, অনগ্রাউড, এনগওয়ার্ড, গ্যাওয়ার্ড .... ইত্যাদি হিসাবে সংরক্ষণ করেছি তাই কোনও সংযুক্ত বাক্যাংশ সর্বদা সূচিকৃত শব্দটির শুরুতে হবে। একটি ভয়াবহ সমাধান, ত্রুটিগুলি পূর্ণ, কিন্তু এটি কার্যকর হয়েছিল।

আমরা তখন দেখার জন্য পৃথক সার্ভার হোস্টিংয়ের দিকে চেয়েছিলাম। গুগলিং লুসিন এবং ইলাস্টিস অনুসন্ধান এগুলিকে শেল্ফ প্যাকেজগুলির বাইরে ভাল তথ্য দেবে।

অবশেষে, আমরা বাড়ি অনুসন্ধান ইঞ্জিনে আমাদের নিজস্ব বিকাশ করেছি, যা এসকিউএল পাশাপাশি চলে। এটি আমাদের ফোনেটিক অনুসন্ধানগুলি (ডাবল मेटाফোন) প্রয়োগ করতে এবং তারপরে প্রাসঙ্গিকতা প্রতিষ্ঠার জন্য সাইড সাউন্ডেক্সের সাথে লেভেনস্টেইন গণনাগুলি ব্যবহার করার অনুমতি দিয়েছে। প্রচুর সমাধানের জন্য ওভারকিল, তবে আমাদের ব্যবহারের ক্ষেত্রে প্রচেষ্টা মূল্যবান। আমাদের কাছে এখন চুদা অনুসন্ধানের জন্য এনভিডিয়া জিপিইউ উপার্জনের বিকল্প রয়েছে, তবে এটি মাথা ব্যাথা এবং নিদ্রাহীন রাতগুলির পুরো নতুন সেটকে উপস্থাপন করে। এই সমস্তগুলির প্রাসঙ্গিকতা আপনি কত ঘন ঘন আপনার অনুসন্ধানগুলি সম্পাদিত হতে দেখেন এবং আপনার সেগুলি কতটা প্রতিক্রিয়াশীল হওয়া দরকার তার উপর নির্ভর করবে।


1

পূর্ণ-পাঠ্য সূচীর কয়েকটি সীমাবদ্ধতা রয়েছে। আপনি শব্দের উপরে ওয়াইল্ডকার্ড ব্যবহার করতে পারেন যা সূচকটি পুরো "অংশ" রয়েছে তবে তারপরেও আপনি শব্দের শেষ অংশে সীমাবদ্ধ রয়েছেন। এজন্য আপনি ব্যবহার করতে পারেন CONTAINS(Name, '"Azimut*"')তবে পারবেন নাCONTAINS(Name, '"zimuth*"')

মাইক্রোসফ্ট ডকুমেন্টেশন থেকে :

উপসর্গ শব্দটি যখন একটি শব্দগুচ্ছ হয়, তখন প্রতিটি টোকেন বাক্যটিকে পৃথক উপসর্গ হিসাবে বিবেচনা করা হয়। উপসর্গ শর্তাবলীতে শব্দের সাথে থাকা সমস্ত সারি ফিরে আসবে। উদাহরণস্বরূপ, "হালকা রুটি *" উপসর্গটি "হালকা রুটিযুক্ত", "হালকা রুটিযুক্ত" বা "হালকা রুটি" এর পাঠ্য সহ সারিগুলি সন্ধান করবে তবে এটি "হালকা টোস্টেড রুটি" ফিরে পাবে না।

ইমেলের বিন্দুগুলি, শিরোনাম দ্বারা নির্দেশিত হিসাবে, প্রধান সমস্যা নয়। এটি উদাহরণস্বরূপ, কাজ করে:

SELECT * FROM NewCompanies 
WHERE CONTAINS((Email, Contacts1, Contacts2, Contacts3, Contacts4), 's.m.s@gmail.com') 

এই ক্ষেত্রে, সূচকটি পুরো ইমেল স্ট্রিংকে বৈধ হিসাবে চিহ্নিত করে, পাশাপাশি "gmail" এবং "gmail.com"। শুধু "এসএমএস" বৈধ নয়।

শেষ উদাহরণটিও একই রকম। ফোন নম্বরটির অংশগুলি সূচকযুক্ত (উদাহরণস্বরূপ 66 666-২২-১১ এবং 999-666-22-11), তবে হাইফেনগুলি অপসারণ এমন কোনও স্ট্রিং নয় যা সূচকটি জানতে পারে। অন্যথায়, এটি কাজ করে:

SELECT * FROM NewCompanies 
WHERE CONTAINS((Phone, Contacts1, Contacts2, Contacts3, Contacts4), '"666-22-11*"')
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.